<commit_before>#include <cmath>
#include <algorithm>
#include <vector>
#include "heapsort.hpp"
#include "insertionSort.hpp"
#include "quicksort.hpp"

#ifndef _INTROSORT_HPP
#define _INTROSORT_HPP 1

namespace Introsort {

  enum { SortThreshold = 16 };

	template<class RandomIt, class SizeType, class Compare>
	void SortLimitedDepth(RandomIt first, RandomIt end, SizeType depthLimit, Compare Comp) {
		while ((end-first) > static_cast<typename std::iterator_traits<RandomIt>::difference_type>(SortThreshold)) {
			if (depthLimit == 0) {
				//Hit our depth limit, do heapsort now
				Heapsort::Sort(first, end, Comp);
				return;
			}
			--depthLimit;
			//Didnt hit the depth limit yet, continue quicksort
			RandomIt partition = Quicksort::Partition(first, end, Comp);
			// SortLimitedDepth(first, partition, depthLimit);
			SortLimitedDepth(partition, end, depthLimit, Comp);
			end = partition;
		}
	}

	template<class RandomIt, class Compare = std::less<typename std::iterator_traits<RandomIt>::value_type>>
	void Sort(RandomIt first, RandomIt end, Compare Comp = Compare()) {
		typename std::iterator_traits<RandomIt>::difference_type length = end-first;
		int maxDepth = 2 * static_cast<int>(log2(length));
		SortLimitedDepth(first, end, maxDepth, Comp);
		//This leaves unsorted chunks of no more than size 'SortThreshold'
		InsertionSort::Sort(first, end, Comp);
	}
}

#endif //_INTROSORT_HPP<commit_msg>added timesort<empty> and used typedef in introsort<commit_after>#include <cmath>
#include <algorithm>
#include <vector>
#include "heapsort.hpp"
#include "insertionSort.hpp"
#include "quicksort.hpp"

#ifndef _INTROSORT_HPP
#define _INTROSORT_HPP 1

namespace Introsort {

  enum { SortThreshold = 16 };

	template<class RandomIt, class SizeType, class Compare>
	void SortLimitedDepth(RandomIt first, RandomIt end, SizeType depthLimit, Compare Comp) {
		typedef typename std::iterator_traits<RandomIt>::difference_type DiffType;
		while ((end-first) > static_cast<DiffType>(SortThreshold)) {
			if (depthLimit == 0) {
				//Hit our depth limit, do heapsort now
				Heapsort::Sort(first, end, Comp);
				return;
			}
			--depthLimit;
			//Didnt hit the depth limit yet, continue quicksort
			RandomIt partition = Quicksort::Partition(first, end, Comp);
			// SortLimitedDepth(first, partition, depthLimit);
			SortLimitedDepth(partition, end, depthLimit, Comp);
			end = partition;
		}
	}

	template<class RandomIt, class Compare = std::less<typename std::iterator_traits<RandomIt>::value_type>>
	void Sort(RandomIt first, RandomIt end, Compare Comp = Compare()) {
		typedef typename std::iterator_traits<RandomIt>::difference_type DiffType;
		DiffType length = end-first;
		int maxDepth = 2 * static_cast<int>(log2(length));
		SortLimitedDepth(first, end, maxDepth, Comp);
		//This leaves unsorted chunks of no more than size 'SortThreshold'
		InsertionSort::Sort(first, end, Comp);
	}
}

#endif //_INTROSORT_HPP<|endoftext|>


<commit_before>#include "Encryption.h"
#include <cstdlib>
#include <time.h>
#include <iostream>

Encryption::Encryption(size_t keyLength) : key(generateRandomKey(keyLength)), current_file_index(0) {
}

Encryption::Encryption(const std::vector<char> & key) : key(key), current_file_index(0) {
}

Encryption::~Encryption() {

}

void Encryption::encryptDecrypt(char* message, size_t length) {
	for (int i = 0; i < length; i++){
		message[i] ^= key[current_file_index++ % (key.size() / sizeof(char))];
	}
}

const std::vector<char> & Encryption::getKey() const {
	return key;
}

std::vector<char> Encryption::generateRandomKey(size_t keyLength) {
    std::vector<char> newKey(keyLength);

	srand(time(NULL));

	for (size_t i = 0; i < keyLength; ++i) {
		newKey[i] = rand() % 100 + 1;
	}

	return std::move(newKey);
}
<commit_msg>Cleaner encryptDecrypt key pos calc<commit_after>#include "Encryption.h"
#include <cstdlib>
#include <time.h>
#include <iostream>

Encryption::Encryption(size_t keyLength) : key(generateRandomKey(keyLength)), current_file_index(0) {
}

Encryption::Encryption(const std::vector<char> & key) : key(key), current_file_index(0) {
}

Encryption::~Encryption() {

}

void Encryption::encryptDecrypt(char* message, size_t length) {
	for (int i = 0; i < length; i++){
		current_file_index = (current_file_index + 1) % key.size();
		message[i] ^= key[current_file_index];
	}
}

const std::vector<char> & Encryption::getKey() const {
	return key;
}

std::vector<char> Encryption::generateRandomKey(size_t keyLength) {
    std::vector<char> newKey(keyLength);

	srand(time(NULL));

	for (size_t i = 0; i < keyLength; ++i) {
		newKey[i] = rand() % 100 + 1;
	}

	return std::move(newKey);
}
<|endoftext|>


<commit_before>#ifndef MERGESORT_HPP
#define MERGESORT_HPP 1

#include <algorithm>
#include <functional>
#include <iterator>
#include <vector>

namespace MergeSort {

	enum class MergeType { InPlace, ExtraSpace };

	template<class RandomIt, class Compare>
	void InPlaceMerge(RandomIt begin, RandomIt middle, RandomIt end, Compare Comp) {
		while (middle != end) {
			while (begin != middle && Comp(*begin, *middle)) {
				++begin;
			}
			if (begin == middle) {
				//All good
				return;
			} else {
				//Need to do a rotate
				//      This moves 'middle' to the position of 'begin',
				//      and shifts [begin, middle) to the right one
				std::rotate(begin, middle, middle+1);
				++begin;
				++middle;
			}
		}
	}

	template<class RandomIt, class Compare>
	void Merge(RandomIt begin, RandomIt middle, RandomIt end, Compare Comp) {
		using ValueType = typename std::iterator_traits<RandomIt>::value_type;

		//Save the left list in a temp because we'll be overwriting it as we insert
		std::vector<ValueType> tempList(begin,middle);
		auto leftIt = tempList.begin();
		auto leftEnd = tempList.end();

		RandomIt rightIt = middle;
		RandomIt rightEnd = end;

		RandomIt insertIt = begin;

		while (leftIt != leftEnd && rightIt != rightEnd) {
			//While there are elements in both lists
			if (Comp(*leftIt,*rightIt)) {
				//Left list's begin element goes begin
				*insertIt = *leftIt;
				++leftIt;
			} else {
				//Right list's begin element goes begin
				*insertIt = *rightIt;
				++rightIt;
			}
			++insertIt;
		}
		//Now at least one list is empty
		if (leftIt != leftEnd) {
			//Insert all of the left list into the list (right is empty)
			std::move(leftIt, leftEnd, insertIt);
		} else if (rightIt != rightEnd) {
			//Insert all of the right list into the list (left is empty)
			std::move(rightIt, rightEnd, insertIt);
		}
	}

	template<class RandomIt, class Compare = std::less<>>
	void Sort(RandomIt begin, RandomIt end, MergeType mergeType = MergeType::ExtraSpace, Compare Comp = Compare()) {
		std::function<void(RandomIt,RandomIt,RandomIt,Compare)> MergeFunction;

		if (mergeType == MergeType::ExtraSpace) {
			MergeFunction = Merge<RandomIt,Compare>;
		} else {
			MergeFunction = InPlaceMerge<RandomIt,Compare>;
		}

		size_t length = std::distance(begin,end);

		for (size_t width=1; width<length; width*=2) {
			//We are going to merge lists of length 'width'
			for (size_t listStart=0; listStart<length; listStart+=(width*2)) {
				//These 2 lists are [listStart, listStart+width) and [listStart+width, listStart+(width*2))
				size_t firstPos = listStart;
				size_t middlePos = listStart+width;
				size_t endPos = listStart+(width*2);
				if (middlePos >= length) {
					middlePos = length;
					endPos = length;
				} else if (endPos >= length) {
					endPos = length;
				}
				MergeFunction(begin+firstPos, begin+middlePos, begin+endPos, Comp);
			}
		}
	}
} //namespace MergeSort

#endif //MERGESORT_HPP<commit_msg>non-working<commit_after>#ifndef MERGESORT_HPP
#define MERGESORT_HPP 1

#include <algorithm>
#include <functional>
#include <iterator>
#include <vector>

namespace MergeSort {

	enum class MergeType { InPlace, ExtraSpace };

	template<class RandomIt, class Compare>
	void InPlaceMerge(RandomIt begin, RandomIt middle, RandomIt end, Compare Comp) {
		while (middle != end) {
			while (begin != middle && Comp(*begin, *middle)) {
				++begin;
			}
			if (begin == middle) {
				//All good
				return;
			} else {
				//Need to do a rotate
				//      This moves 'middle' to the position of 'begin',
				//      and shifts [begin, middle) to the right one
				std::rotate(begin, middle, middle+1);
				++begin;
				++middle;
			}
		}
	}

	template<class RandomIt, class Compare>
	void Merge(RandomIt begin, RandomIt middle, RandomIt end, Compare Comp) {
		size_t leftLength = std::distance(begin, middle);
		size_t rightLength = std::distance(middle, end);

		if (leftLength > rightLength) {
			using ReverseIterator = std::reverse_iterator<RandomIt>;
			Merge(ReverseIterator(end), ReverseIterator(std::next(middle)), ReverseIterator(begin), Comp);
			return;
		}

		using ValueType = typename std::iterator_traits<RandomIt>::value_type;

		//Save the left list in a temp because we'll be overwriting it as we insert
		std::vector<ValueType> tempList(begin,middle);
		auto leftIt = tempList.begin();
		auto leftEnd = tempList.end();

		RandomIt rightIt = middle;
		RandomIt rightEnd = end;

		RandomIt insertIt = begin;

		while (leftIt != leftEnd && rightIt != rightEnd) {
			//While there are elements in both lists
			if (Comp(*leftIt,*rightIt)) {
				//Left list's begin element goes begin
				*insertIt = *leftIt;
				++leftIt;
			} else {
				//Right list's begin element goes begin
				*insertIt = *rightIt;
				++rightIt;
			}
			++insertIt;
		}
		//Now at least one list is empty
		if (leftIt != leftEnd) {
			//Insert all of the left list into the list (right is empty)
			std::move(leftIt, leftEnd, insertIt);
		} else if (rightIt != rightEnd) {
			//Insert all of the right list into the list (left is empty)
			std::move(rightIt, rightEnd, insertIt);
		}
	}

	template<class RandomIt, class Compare = std::less<>>
	void Sort(RandomIt begin, RandomIt end, MergeType mergeType = MergeType::ExtraSpace, Compare Comp = Compare()) {
		std::function<void(RandomIt,RandomIt,RandomIt,Compare)> MergeFunction;

		if (mergeType == MergeType::ExtraSpace) {
			MergeFunction = Merge<RandomIt,Compare>;
		} else {
			MergeFunction = InPlaceMerge<RandomIt,Compare>;
		}

		size_t length = std::distance(begin,end);

		for (size_t width=1; width<length; width*=2) {
			//We are going to merge lists of length 'width'
			for (size_t listStart=0; listStart<length; listStart+=(width*2)) {
				//These 2 lists are [listStart, listStart+width) and [listStart+width, listStart+(width*2))
				size_t firstPos = listStart;
				size_t middlePos = listStart+width;
				size_t endPos = listStart+(width*2);
				if (middlePos >= length) {
					middlePos = length;
					endPos = length;
				} else if (endPos >= length) {
					endPos = length;
				}
				MergeFunction(begin+firstPos, begin+middlePos, begin+endPos, Comp);
			}
		}
	}
} //namespace MergeSort

#endif //MERGESORT_HPP<|endoftext|>


<commit_before>#include "rdb.hpp"
#include <cstring>
#include <cstdio>

void fatal(const char*, ...);

void usage(void);

int main(int argc, char *argv[]) {
	if (argc < 2)
		usage();

	const char *root = argv[1];

	RdbAttrs attrs;
	for (int i = 2; i < argc; i++) {
		char *key = argv[i];
		char *vl = strchr(key, '=');
		if (!vl)
			usage();
		vl[0] = '\0';
		vl++;
		attrs.push_back(key, vl);
	}

	printf("%s\n", rdbpathfor(root, attrs).c_str());
	return 0;
}

void usage(void) {
	fatal("Usage: pathfor <root> <key>=<value>*\n");
}<commit_msg>rdb: better handling of keys with spaces in pathfor.<commit_after>#include "rdb.hpp"
#include <cstring>
#include <cstdio>

void fatal(const char*, ...);

void usage(void);
int nextpair(int, char *[], std::string&, std::string&);

int main(int argc, char *argv[]) {
	if (argc < 2)
		usage();

	const char *root = argv[1];

	RdbAttrs attrs;
	argc -= 2;
	argv+= 2;
	while (argc > 0) {
		std::string key, value;
		int shift = nextpair(argc, argv, key, value);
		argc -= shift;
		argv += shift;
		attrs.push_back(key.c_str(), value.c_str());
	}

	printf("%s\n", rdbpathfor(root, attrs).c_str());
	return 0;
}

void usage(void) {
	fatal("Usage: pathfor <root> <key>=<value>*\n");
}

int nextpair(int argc, char *argv[], std::string &key, std::string &value) {
	key.clear();
	value.clear();

	for (int i = 0; i < argc; i++) {
		char *vl =strchr(argv[i], '=');
		if (!vl) {
			key += argv[i];
			key.push_back(' ');
			continue;
		}
		vl[0] = '\0';
		key += argv[i];
		value = vl+1;
		return i+1;
	}
	usage();
	return -1;	// unreachable
}<|endoftext|>


<commit_before>#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <RF24/RF24.h>
#include <curses.h>
#include <menu.h>

#include "../glowworm/glowworm_core.h"
#include "../cauldron/cauldron_core.h"
#include "controller.h"

using namespace std;

#define INTERVAL 3	/* The send interval (in ms) */

RF24 * const radio = new RF24(RPI_GPIO_P1_22, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ);

glowworm_config * const glowworm = new glowworm_config();
cauldron_config * const cauldron = new cauldron_config();

WINDOW * menuWindow;
WINDOW * infoWindow;

int main(int argc, char** argv){
	// Setup the radio
	setupRadio();
	setupRadio(PROGRAM_GLOWWORM);

	// Initialise the ncurses window
	initscr();
	cbreak();
	noecho();
	keypad(stdscr, TRUE);

	menuWindow = newwin(20, 40, 0, 0);
	infoWindow = newwin(20, 40, 0, 40);

	while (createMenu(PROGRAM_EXIT)) {
	}

	endwin();

	return 0;
}

bool createMenu(program_e prog) {
	// The ncurses menu
	ITEM ** myItems;
	int c;
	MENU * myMenu;
	uint8_t menuCount;
	const char ** descriptions;
	ITEM * currentItem;

	// Which menu should be displayed
	switch (prog) {
		case PROGRAM_BOTTLES:
			descriptions = BOTTLES_MENU;
			menuCount = ARRAY_SIZE(BOTTLES_MENU);
			break;

		case PROGRAM_CAULDRON:
			descriptions = CAULDRON_MENU;
			menuCount = ARRAY_SIZE(CAULDRON_MENU);
			break;

		case PROGRAM_GLOWWORM:
			descriptions = GLOWWORM_MENU;
			menuCount = ARRAY_SIZE(GLOWWORM_MENU);
			break;

		default:
			descriptions = MAIN_MENU;
			menuCount = ARRAY_SIZE(MAIN_MENU);
			break;

	}

	// Allocate the menu items and create them
	myItems = (ITEM **)calloc(menuCount + 1, sizeof(ITEM *));
	for (uint8_t i = 0; i < menuCount; i++) {
		myItems[i] = new_item(descriptions[i], NULL); // Don't need a description
	}
	myItems[menuCount] = (ITEM *)NULL;

	myMenu = new_menu((ITEM **)myItems);

	// Prepare the menu window
	wclear(menuWindow);
	box(menuWindow, 0, 0);
 	set_menu_win(myMenu, menuWindow);
	set_menu_sub(myMenu, derwin(menuWindow, 16, 38, 3, 1));

	// Menu window title uses the current selection
	// and a separator
	mvwaddch(menuWindow, 2, 0, ACS_LTEE);
	mvwhline(menuWindow, 2, 1, ACS_HLINE, 38);
	mvwaddch(menuWindow, 2, 39, ACS_RTEE);
	mvwprintw(menuWindow, 1, 3,
		prog == PROGRAM_EXIT ? "Select a Program" : MAIN_MENU[prog]);

	// And draw it
	refresh();
	post_menu(myMenu);
	wrefresh(menuWindow);

	// Redraw the information window
	wclear(infoWindow);
	box(infoWindow, 0,0);
	wrefresh(infoWindow);

	// Focus on the menu window
	keypad(menuWindow, TRUE);

	program_e newProg = PROGRAM_EXIT;
	while ((c = getch())) {
		bool quit = false;
		switch (c) {
			case KEY_DOWN:
				menu_driver(myMenu, REQ_DOWN_ITEM);
				break;

			case KEY_UP:
				menu_driver(myMenu, REQ_UP_ITEM);
				break;

			case 10: // Enter
				currentItem = current_item(myMenu);
				int index = item_index(currentItem);
				if (prog == PROGRAM_EXIT) {
					quit = true;
					newProg = (program_e)index;
				} else if (index == 0)  {
					quit = true;
				} else {
					// Just do what ever was requested
					programMenuSelected(prog, currentItem);
				}
				break;
		}

		if (quit) {
			break;
		} else {
			// Need to refresh the window to register the selection change
			wrefresh(menuWindow);
		}
	}

	unpost_menu(myMenu);
	for (uint8_t i = 0; i < menuCount; i++) {
		free_item(myItems[i]);
	}
	free_menu(myMenu);

	if (prog == PROGRAM_EXIT) {
		if (newProg == PROGRAM_EXIT) {
			return false; // Signal that we want to quit
		} else {
			createMenu(newProg); // Draw the requested program menu
		}
	}

	return true;
}

bool doBottles(bottles_e command) {
	switch (command) {
		default:
			return true;
	}
}

bool doCauldron(cauldron_e command) {
	switch (command) {
		case CAULDRON_OFF:
			return writeCauldron(CAULDRON_MODE_NONE);

		case CAULDRON_TOGGLE_ALL:
			return writeCauldron((cauldron_mode_e)(cauldron->mode ^ CAULDRON_MODE_ALL));

		case CAULDRON_TOGGLE_FAN:
			return writeCauldron((cauldron_mode_e)(cauldron->mode ^ CAULDRON_MODE_FAN));

		case CAULDRON_TOGGLE_FIRE:
			return writeCauldron((cauldron_mode_e)(cauldron->mode ^ CAULDRON_MODE_FIRE));

		case CAULDRON_TOGGLE_GLOW:
			return writeCauldron((cauldron_mode_e)(cauldron->mode ^ CAULDRON_MODE_GLOW));

		default:
			return true;
	}
}

bool doGlowworm(glowworm_e command) {
	switch (command) {
		case GLOWWORM_OFF:
			return writeGlowworm(ANTENNA_NONE, 0, 0, 0);

		case GLOWWORM_TOGGLE_BOTH:
			return writeGlowworm((antenna_e)(glowworm->antenna ^ ANTENNA_BOTH));

		case GLOWWORM_TOGGLE_LEFT:
			return writeGlowworm((antenna_e)(glowworm->antenna ^ ANTENNA_LEFT));

		case GLOWWORM_TOGGLE_RIGHT:
			return writeGlowworm((antenna_e)(glowworm->antenna ^ ANTENNA_RIGHT));

		case GLOWWORM_RED:
			return writeGlowworm(0xff, 0, 0);

		case GLOWWORM_GREEN:
			return writeGlowworm(0, 0xff, 0);

		case GLOWWORM_BLUE:
			return writeGlowworm(0,0, 0xff);

		case GLOWWORM_YELLOW:
			return writeGlowworm(0xff, 0xff, 0);

		case GLOWWORM_PINK:
			return writeGlowworm(0xff, 0x14,0x93); // Deep Pink

		default:
			return true;
	}
}

void programMenuSelected(program_e prog, ITEM * item) {
	// Set up the radio for the particular program
	setupRadio(prog);

	int index = item_index(item);

	switch (prog) {
		case PROGRAM_BOTTLES:
			doBottles((bottles_e)index);
			break;

		case PROGRAM_CAULDRON:
			doCauldron((cauldron_e)index);
			break;

		case PROGRAM_GLOWWORM:
			doGlowworm((glowworm_e)index);
			break;

		default:
			break;

	}
}

void setupRadio() {
	// HACK: Do the startup of the scanner app
	// I think this makes it go into standby
	radio->begin();
	radio->setAutoAck(false);
	radio->startListening();
	radio->stopListening();

	radio->begin();
	radio->setAutoAck(true);
	radio->setChannel(CHANNEL);

	//radio->enableAckPayload(); // So we can send a response back
	radio->setRetries(RETRY_DELAY, RETRY_COUNT); // How often and how many times to retry

	// Use High power, and slowest rate
	radio->setPALevel(RF24_PA_HIGH);
	radio->setDataRate(RF24_250KBPS);
}

void setupRadio(program_e prog) {
	radio->stopListening();
	size_t payload;

	switch (prog) {
		case PROGRAM_CAULDRON:
			payload = sizeof(cauldron_config);
			break;

		case PROGRAM_GLOWWORM:
			payload = sizeof(glowworm_config);
			break;

		default:
			return;

	}

	radio->setPayloadSize(payload);
	radio->openReadingPipe(1, addresses[0]);
	radio->openWritingPipe(addresses[prog]);

	radio->startListening();
}

bool writeCauldron(cauldron_mode_e mode) {
	cauldron->mode = mode;

	mvwprintw(infoWindow, 1, 1, "Fan:   %s", (mode & CAULDRON_MODE_FAN) ? "On" : "Off");
	mvwprintw(infoWindow, 2, 1, "Fire:  %s", (mode & CAULDRON_MODE_FIRE) ? "On" : "Off");
	mvwprintw(infoWindow, 3, 1, "Glow:  %s", (mode & CAULDRON_MODE_GLOW) ? "On" : "Off");

	wrefresh(infoWindow);

	cauldron_config * response = new cauldron_config();

	bool success = writeRadio(cauldron, sizeof(cauldron), response);

	delete response;

	return success;
}

bool writeGlowworm(antenna_e antenna) {
	return writeGlowworm(antenna, glowworm->r, glowworm->g, glowworm->b);
}

bool writeGlowworm(uint8_t r, uint8_t g, uint8_t b) {
	return writeGlowworm((antenna_e)glowworm->antenna, r, g, b);
}

bool writeGlowworm(antenna_e antenna, uint8_t r, uint8_t g, uint8_t b) {
	glowworm->antenna = antenna;
	glowworm->r = r;
	glowworm->g = g;
	glowworm->b = b;

	mvwprintw(infoWindow, 1, 1, "Antenna: %i", antenna);
	mvwprintw(infoWindow, 2, 1, "Red:     0x%02x", r);
	mvwprintw(infoWindow, 3, 1, "Green:   0x%02x", g);
	mvwprintw(infoWindow, 4, 1, "Blue:    0x%02x", b);

	mvprintw(LINES - 3, 0,
		"Sending: Antenna: %i, R: 0x%02x, G: 0x%02x, B: 0x%02x ...\n",
		antenna, r, g, b);

	wrefresh(infoWindow);

	glowworm_config * response = new glowworm_config();

	bool success = writeRadio(glowworm, sizeof(glowworm), response);

	delete response;

	return success;
}

bool writeRadio(void * payload, size_t length, void * response) {
	// Stop listening so we can send
	radio->stopListening();

	// Current time so we can measure the response time
	uint32_t time = millis();

	mvprintw(LINES - 2, 0, "Sending %i bytes...", length);
	bool ok = radio->write(payload, length);
	mvprintw(LINES - 2, 20, "%s\n", ok ? "done" : "failed");

	// Start listening agains so we can receive the response
	radio->startListening();

	uint32_t startedWaiting = millis();
	bool timeout = false;
	while (!radio->available() &&  !timeout) {
		if ((millis() - startedWaiting) > TIMEOUT) {
			timeout = true;
		}
	}

	uint32_t pingTime = millis() - time;

	// What happened
	if (timeout) {
		mvprintw(LINES - 1, 0, "Failed - response timed out after %u.\n", TIMEOUT);
	} else {
		radio->read(response, length);
		mvprintw(LINES - 1, 0, "Received %i bytes - round-trip delay: %u\n", length, pingTime);
		mvprintw(LINES - 1, 0, "Success");
	}

	return true;
}
<commit_msg>Turn on antennae with pink<commit_after>#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <RF24/RF24.h>
#include <curses.h>
#include <menu.h>

#include "../glowworm/glowworm_core.h"
#include "../cauldron/cauldron_core.h"
#include "controller.h"

using namespace std;

#define INTERVAL 3	/* The send interval (in ms) */

RF24 * const radio = new RF24(RPI_GPIO_P1_22, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_8MHZ);

glowworm_config * const glowworm = new glowworm_config();
cauldron_config * const cauldron = new cauldron_config();

WINDOW * menuWindow;
WINDOW * infoWindow;

int main(int argc, char** argv){
	// Setup the radio
	setupRadio();
	setupRadio(PROGRAM_GLOWWORM);

	// Initialise the ncurses window
	initscr();
	cbreak();
	noecho();
	keypad(stdscr, TRUE);

	menuWindow = newwin(20, 40, 0, 0);
	infoWindow = newwin(20, 40, 0, 40);

	while (createMenu(PROGRAM_EXIT)) {
	}

	endwin();

	return 0;
}

bool createMenu(program_e prog) {
	// The ncurses menu
	ITEM ** myItems;
	int c;
	MENU * myMenu;
	uint8_t menuCount;
	const char ** descriptions;
	ITEM * currentItem;

	// Which menu should be displayed
	switch (prog) {
		case PROGRAM_BOTTLES:
			descriptions = BOTTLES_MENU;
			menuCount = ARRAY_SIZE(BOTTLES_MENU);
			break;

		case PROGRAM_CAULDRON:
			descriptions = CAULDRON_MENU;
			menuCount = ARRAY_SIZE(CAULDRON_MENU);
			break;

		case PROGRAM_GLOWWORM:
			descriptions = GLOWWORM_MENU;
			menuCount = ARRAY_SIZE(GLOWWORM_MENU);
			break;

		default:
			descriptions = MAIN_MENU;
			menuCount = ARRAY_SIZE(MAIN_MENU);
			break;

	}

	// Allocate the menu items and create them
	myItems = (ITEM **)calloc(menuCount + 1, sizeof(ITEM *));
	for (uint8_t i = 0; i < menuCount; i++) {
		myItems[i] = new_item(descriptions[i], NULL); // Don't need a description
	}
	myItems[menuCount] = (ITEM *)NULL;

	myMenu = new_menu((ITEM **)myItems);

	// Prepare the menu window
	wclear(menuWindow);
	box(menuWindow, 0, 0);
 	set_menu_win(myMenu, menuWindow);
	set_menu_sub(myMenu, derwin(menuWindow, 16, 38, 3, 1));

	// Menu window title uses the current selection
	// and a separator
	mvwaddch(menuWindow, 2, 0, ACS_LTEE);
	mvwhline(menuWindow, 2, 1, ACS_HLINE, 38);
	mvwaddch(menuWindow, 2, 39, ACS_RTEE);
	mvwprintw(menuWindow, 1, 3,
		prog == PROGRAM_EXIT ? "Select a Program" : MAIN_MENU[prog]);

	// And draw it
	refresh();
	post_menu(myMenu);
	wrefresh(menuWindow);

	// Redraw the information window
	wclear(infoWindow);
	box(infoWindow, 0,0);
	wrefresh(infoWindow);

	// Focus on the menu window
	keypad(menuWindow, TRUE);

	program_e newProg = PROGRAM_EXIT;
	while ((c = getch())) {
		bool quit = false;
		switch (c) {
			case KEY_DOWN:
				menu_driver(myMenu, REQ_DOWN_ITEM);
				break;

			case KEY_UP:
				menu_driver(myMenu, REQ_UP_ITEM);
				break;

			case 10: // Enter
				currentItem = current_item(myMenu);
				int index = item_index(currentItem);
				if (prog == PROGRAM_EXIT) {
					quit = true;
					newProg = (program_e)index;
				} else if (index == 0)  {
					quit = true;
				} else {
					// Just do what ever was requested
					programMenuSelected(prog, currentItem);
				}
				break;
		}

		if (quit) {
			break;
		} else {
			// Need to refresh the window to register the selection change
			wrefresh(menuWindow);
		}
	}

	unpost_menu(myMenu);
	for (uint8_t i = 0; i < menuCount; i++) {
		free_item(myItems[i]);
	}
	free_menu(myMenu);

	if (prog == PROGRAM_EXIT) {
		if (newProg == PROGRAM_EXIT) {
			return false; // Signal that we want to quit
		} else {
			createMenu(newProg); // Draw the requested program menu
		}
	}

	return true;
}

bool doBottles(bottles_e command) {
	switch (command) {
		default:
			return true;
	}
}

bool doCauldron(cauldron_e command) {
	switch (command) {
		case CAULDRON_OFF:
			return writeCauldron(CAULDRON_MODE_NONE);

		case CAULDRON_TOGGLE_ALL:
			return writeCauldron((cauldron_mode_e)(cauldron->mode ^ CAULDRON_MODE_ALL));

		case CAULDRON_TOGGLE_FAN:
			return writeCauldron((cauldron_mode_e)(cauldron->mode ^ CAULDRON_MODE_FAN));

		case CAULDRON_TOGGLE_FIRE:
			return writeCauldron((cauldron_mode_e)(cauldron->mode ^ CAULDRON_MODE_FIRE));

		case CAULDRON_TOGGLE_GLOW:
			return writeCauldron((cauldron_mode_e)(cauldron->mode ^ CAULDRON_MODE_GLOW));

		default:
			return true;
	}
}

bool doGlowworm(glowworm_e command) {
	switch (command) {
		case GLOWWORM_OFF:
			return writeGlowworm(ANTENNA_NONE, 0, 0, 0);

		case GLOWWORM_TOGGLE_BOTH:
			return writeGlowworm((antenna_e)(glowworm->antenna ^ ANTENNA_BOTH));

		case GLOWWORM_TOGGLE_LEFT:
			return writeGlowworm((antenna_e)(glowworm->antenna ^ ANTENNA_LEFT));

		case GLOWWORM_TOGGLE_RIGHT:
			return writeGlowworm((antenna_e)(glowworm->antenna ^ ANTENNA_RIGHT));

		case GLOWWORM_RED:
			return writeGlowworm(0xff, 0, 0);

		case GLOWWORM_GREEN:
			return writeGlowworm(0, 0xff, 0);

		case GLOWWORM_BLUE:
			return writeGlowworm(0,0, 0xff);

		case GLOWWORM_YELLOW:
			return writeGlowworm(0xff, 0xff, 0);

		case GLOWWORM_PINK:
			return writeGlowworm(ANTENNA_BOTH, 0xff, 0x14,0x93); // Deep Pink

		default:
			return true;
	}
}

void programMenuSelected(program_e prog, ITEM * item) {
	// Set up the radio for the particular program
	setupRadio(prog);

	int index = item_index(item);

	switch (prog) {
		case PROGRAM_BOTTLES:
			doBottles((bottles_e)index);
			break;

		case PROGRAM_CAULDRON:
			doCauldron((cauldron_e)index);
			break;

		case PROGRAM_GLOWWORM:
			doGlowworm((glowworm_e)index);
			break;

		default:
			break;

	}
}

void setupRadio() {
	// HACK: Do the startup of the scanner app
	// I think this makes it go into standby
	radio->begin();
	radio->setAutoAck(false);
	radio->startListening();
	radio->stopListening();

	radio->begin();
	radio->setAutoAck(true);
	radio->setChannel(CHANNEL);

	//radio->enableAckPayload(); // So we can send a response back
	radio->setRetries(RETRY_DELAY, RETRY_COUNT); // How often and how many times to retry

	// Use High power, and slowest rate
	radio->setPALevel(RF24_PA_HIGH);
	radio->setDataRate(RF24_250KBPS);
}

void setupRadio(program_e prog) {
	radio->stopListening();
	size_t payload;

	switch (prog) {
		case PROGRAM_CAULDRON:
			payload = sizeof(cauldron_config);
			break;

		case PROGRAM_GLOWWORM:
			payload = sizeof(glowworm_config);
			break;

		default:
			return;

	}

	radio->setPayloadSize(payload);
	radio->openReadingPipe(1, addresses[0]);
	radio->openWritingPipe(addresses[prog]);

	radio->startListening();
}

bool writeCauldron(cauldron_mode_e mode) {
	cauldron->mode = mode;

	mvwprintw(infoWindow, 1, 1, "Fan:   %s", (mode & CAULDRON_MODE_FAN) ? "On" : "Off");
	mvwprintw(infoWindow, 2, 1, "Fire:  %s", (mode & CAULDRON_MODE_FIRE) ? "On" : "Off");
	mvwprintw(infoWindow, 3, 1, "Glow:  %s", (mode & CAULDRON_MODE_GLOW) ? "On" : "Off");

	wrefresh(infoWindow);

	cauldron_config * response = new cauldron_config();

	bool success = writeRadio(cauldron, sizeof(cauldron), response);

	delete response;

	return success;
}

bool writeGlowworm(antenna_e antenna) {
	return writeGlowworm(antenna, glowworm->r, glowworm->g, glowworm->b);
}

bool writeGlowworm(uint8_t r, uint8_t g, uint8_t b) {
	return writeGlowworm((antenna_e)glowworm->antenna, r, g, b);
}

bool writeGlowworm(antenna_e antenna, uint8_t r, uint8_t g, uint8_t b) {
	glowworm->antenna = antenna;
	glowworm->r = r;
	glowworm->g = g;
	glowworm->b = b;

	mvwprintw(infoWindow, 1, 1, "Antenna: %i", antenna);
	mvwprintw(infoWindow, 2, 1, "Red:     0x%02x", r);
	mvwprintw(infoWindow, 3, 1, "Green:   0x%02x", g);
	mvwprintw(infoWindow, 4, 1, "Blue:    0x%02x", b);

	mvprintw(LINES - 3, 0,
		"Sending: Antenna: %i, R: 0x%02x, G: 0x%02x, B: 0x%02x ...\n",
		antenna, r, g, b);

	wrefresh(infoWindow);

	glowworm_config * response = new glowworm_config();

	bool success = writeRadio(glowworm, sizeof(glowworm), response);

	delete response;

	return success;
}

bool writeRadio(void * payload, size_t length, void * response) {
	// Stop listening so we can send
	radio->stopListening();

	// Current time so we can measure the response time
	uint32_t time = millis();

	mvprintw(LINES - 2, 0, "Sending %i bytes...", length);
	bool ok = radio->write(payload, length);
	mvprintw(LINES - 2, 20, "%s\n", ok ? "done" : "failed");

	// Start listening agains so we can receive the response
	radio->startListening();

	uint32_t startedWaiting = millis();
	bool timeout = false;
	while (!radio->available() &&  !timeout) {
		if ((millis() - startedWaiting) > TIMEOUT) {
			timeout = true;
		}
	}

	uint32_t pingTime = millis() - time;

	// What happened
	if (timeout) {
		mvprintw(LINES - 1, 0, "Failed - response timed out after %u.\n", TIMEOUT);
	} else {
		radio->read(response, length);
		mvprintw(LINES - 1, 0, "Received %i bytes - round-trip delay: %u\n", length, pingTime);
		mvprintw(LINES - 1, 0, "Success");
	}

	return true;
}
<|endoftext|>


<commit_before>/* libs/graphics/sgl/SkColorTable.cpp
**
** Copyright 2006, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#include "SkBitmap.h"
#include "SkFlattenable.h"
#include "SkStream.h"
#include "SkTemplates.h"

SkColorTable::SkColorTable(int count)
    : f16BitCache(NULL), fFlags(0)
{
    if (count < 0)
        count = 0;
    else if (count > 256)
        count = 256;

    fCount = SkToU16(count);
    fColors = (SkPMColor*)sk_malloc_throw(count * sizeof(SkPMColor));
    memset(fColors, 0, count * sizeof(SkPMColor));

    SkDEBUGCODE(fColorLockCount = 0;)
    SkDEBUGCODE(f16BitCacheLockCount = 0;)
}

SkColorTable::SkColorTable(const SkColorTable& src) {
    f16BitCache = NULL;
    fFlags = src.fFlags;
    int count = src.count();
    fCount = SkToU16(count);
    fColors = (SkPMColor*)sk_malloc_throw(count * sizeof(SkPMColor));
    memcpy(fColors, src.fColors, count * sizeof(SkPMColor));

    SkDEBUGCODE(fColorLockCount = 0;)
    SkDEBUGCODE(f16BitCacheLockCount = 0;)
}

SkColorTable::SkColorTable(const SkPMColor colors[], int count)
    : f16BitCache(NULL), fFlags(0)
{
    if (count < 0)
        count = 0;
    else if (count > 256)
        count = 256;

    fCount = SkToU16(count);
    fColors = (SkPMColor*)sk_malloc_throw(count * sizeof(SkPMColor));

    if (colors)
        memcpy(fColors, colors, count * sizeof(SkPMColor));

    SkDEBUGCODE(fColorLockCount = 0;)
    SkDEBUGCODE(f16BitCacheLockCount = 0;)
}

SkColorTable::~SkColorTable()
{
    SkASSERT(fColorLockCount == 0);
    SkASSERT(f16BitCacheLockCount == 0);

    sk_free(fColors);
    sk_free(f16BitCache);
}

void SkColorTable::setFlags(unsigned flags)
{
    fFlags = SkToU8(flags);
}

void SkColorTable::unlockColors(bool changed)
{
    SkASSERT(fColorLockCount != 0);
    SkDEBUGCODE(fColorLockCount -= 1;)
    if (changed)
        this->inval16BitCache();
}

void SkColorTable::inval16BitCache()
{
    SkASSERT(f16BitCacheLockCount == 0);
    if (f16BitCache)
    {
        sk_free(f16BitCache);
        f16BitCache = NULL;
    }
}

#include "SkColorPriv.h"

static inline void build_16bitcache(uint16_t dst[], const SkPMColor src[], int count)
{
    while (--count >= 0)
        *dst++ = SkPixel32ToPixel16_ToU16(*src++);
}

const uint16_t* SkColorTable::lock16BitCache()
{
    if (fFlags & kColorsAreOpaque_Flag)
    {
        if (f16BitCache == NULL) // build the cache
        {
            f16BitCache = (uint16_t*)sk_malloc_throw(fCount * sizeof(uint16_t));
            build_16bitcache(f16BitCache, fColors, fCount);
        }
    }
    else    // our colors have alpha, so no cache
    {
        this->inval16BitCache();
        if (f16BitCache)
        {
            sk_free(f16BitCache);
            f16BitCache = NULL;
        }
    }

    SkDEBUGCODE(f16BitCacheLockCount += 1);
    return f16BitCache;
}

///////////////////////////////////////////////////////////////////////////////

SkColorTable::SkColorTable(SkFlattenableReadBuffer& buffer) {
    f16BitCache = NULL;
    SkDEBUGCODE(fColorLockCount = 0;)
    SkDEBUGCODE(f16BitCacheLockCount = 0;)

    fCount = buffer.readU16();
    SkASSERT((unsigned)fCount <= 256);

    fFlags = buffer.readU8();

    fColors = (SkPMColor*)sk_malloc_throw(fCount * sizeof(SkPMColor));
    buffer.read(fColors, fCount * sizeof(SkPMColor));
}

void SkColorTable::flatten(SkFlattenableWriteBuffer& buffer) const {
    int count = this->count();
    buffer.write16(count);
    buffer.write8(this->getFlags());
    buffer.writeMul4(fColors, count * sizeof(SkPMColor));
}

<commit_msg>update license header<commit_after>/*
 * Copyright (C) 2006-2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "SkBitmap.h"
#include "SkFlattenable.h"
#include "SkStream.h"
#include "SkTemplates.h"

SkColorTable::SkColorTable(int count)
    : f16BitCache(NULL), fFlags(0)
{
    if (count < 0)
        count = 0;
    else if (count > 256)
        count = 256;

    fCount = SkToU16(count);
    fColors = (SkPMColor*)sk_malloc_throw(count * sizeof(SkPMColor));
    memset(fColors, 0, count * sizeof(SkPMColor));

    SkDEBUGCODE(fColorLockCount = 0;)
    SkDEBUGCODE(f16BitCacheLockCount = 0;)
}

SkColorTable::SkColorTable(const SkColorTable& src) {
    f16BitCache = NULL;
    fFlags = src.fFlags;
    int count = src.count();
    fCount = SkToU16(count);
    fColors = reinterpret_cast<SkPMColor*>(
                                    sk_malloc_throw(count * sizeof(SkPMColor)));
    memcpy(fColors, src.fColors, count * sizeof(SkPMColor));

    SkDEBUGCODE(fColorLockCount = 0;)
    SkDEBUGCODE(f16BitCacheLockCount = 0;)
}

SkColorTable::SkColorTable(const SkPMColor colors[], int count)
    : f16BitCache(NULL), fFlags(0)
{
    if (count < 0)
        count = 0;
    else if (count > 256)
        count = 256;

    fCount = SkToU16(count);
    fColors = reinterpret_cast<SkPMColor*>(
                                    sk_malloc_throw(count * sizeof(SkPMColor)));

    if (colors)
        memcpy(fColors, colors, count * sizeof(SkPMColor));

    SkDEBUGCODE(fColorLockCount = 0;)
    SkDEBUGCODE(f16BitCacheLockCount = 0;)
}

SkColorTable::~SkColorTable()
{
    SkASSERT(fColorLockCount == 0);
    SkASSERT(f16BitCacheLockCount == 0);

    sk_free(fColors);
    sk_free(f16BitCache);
}

void SkColorTable::setFlags(unsigned flags)
{
    fFlags = SkToU8(flags);
}

void SkColorTable::unlockColors(bool changed)
{
    SkASSERT(fColorLockCount != 0);
    SkDEBUGCODE(fColorLockCount -= 1;)
    if (changed)
        this->inval16BitCache();
}

void SkColorTable::inval16BitCache()
{
    SkASSERT(f16BitCacheLockCount == 0);
    if (f16BitCache)
    {
        sk_free(f16BitCache);
        f16BitCache = NULL;
    }
}

#include "SkColorPriv.h"

static inline void build_16bitcache(uint16_t dst[], const SkPMColor src[], int count)
{
    while (--count >= 0)
        *dst++ = SkPixel32ToPixel16_ToU16(*src++);
}

const uint16_t* SkColorTable::lock16BitCache()
{
    if (fFlags & kColorsAreOpaque_Flag)
    {
        if (f16BitCache == NULL) // build the cache
        {
            f16BitCache = (uint16_t*)sk_malloc_throw(fCount * sizeof(uint16_t));
            build_16bitcache(f16BitCache, fColors, fCount);
        }
    }
    else    // our colors have alpha, so no cache
    {
        this->inval16BitCache();
        if (f16BitCache)
        {
            sk_free(f16BitCache);
            f16BitCache = NULL;
        }
    }

    SkDEBUGCODE(f16BitCacheLockCount += 1);
    return f16BitCache;
}

///////////////////////////////////////////////////////////////////////////////

SkColorTable::SkColorTable(SkFlattenableReadBuffer& buffer) {
    f16BitCache = NULL;
    SkDEBUGCODE(fColorLockCount = 0;)
    SkDEBUGCODE(f16BitCacheLockCount = 0;)

    fCount = buffer.readU16();
    SkASSERT((unsigned)fCount <= 256);

    fFlags = buffer.readU8();

    fColors = (SkPMColor*)sk_malloc_throw(fCount * sizeof(SkPMColor));
    buffer.read(fColors, fCount * sizeof(SkPMColor));
}

void SkColorTable::flatten(SkFlattenableWriteBuffer& buffer) const {
    int count = this->count();
    buffer.write16(count);
    buffer.write8(this->getFlags());
    buffer.writeMul4(fColors, count * sizeof(SkPMColor));
}

<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2018, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of the copyright holder nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file
 *   This file implements ECDSA signing.
 */

#include "ecdsa.hpp"

#include <mbedtls/ecdsa.h>
#include <mbedtls/pk.h>

#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/random.hpp"

namespace ot {
namespace Crypto {

#if OPENTHREAD_ENABLE_ECDSA

otError Ecdsa::Sign(uint8_t *      aOutput,
                    uint16_t *     aOutputLength,
                    const uint8_t *aInputHash,
                    uint16_t       aInputHashLength,
                    const uint8_t *aPrivateKey,
                    uint16_t       aPrivateKeyLength)
{
    otError               error = OT_ERROR_NONE;
    mbedtls_ecdsa_context ctx;
    mbedtls_pk_context    pkCtx;
    mbedtls_ecp_keypair * keypair;
    mbedtls_mpi           rMpi;
    mbedtls_mpi           sMpi;

    mbedtls_pk_init(&pkCtx);
    mbedtls_ecdsa_init(&ctx);
    mbedtls_mpi_init(&rMpi);
    mbedtls_mpi_init(&sMpi);

    // Parse a private key in PEM format.
    VerifyOrExit(mbedtls_pk_parse_key(&pkCtx, aPrivateKey, aPrivateKeyLength, NULL, 0) == 0,
                 error = OT_ERROR_INVALID_ARGS);
    VerifyOrExit(mbedtls_pk_get_type(&pkCtx) == MBEDTLS_PK_ECKEY, error = OT_ERROR_INVALID_ARGS);

    keypair = mbedtls_pk_ec(pkCtx);
    assert(keypair != NULL);

    VerifyOrExit(mbedtls_ecdsa_from_keypair(&ctx, keypair) == 0, error = OT_ERROR_FAILED);

    // Sign using ECDSA.
    VerifyOrExit(mbedtls_ecdsa_sign(&ctx.grp, &rMpi, &sMpi, &ctx.d, aInputHash, aInputHashLength, FillRandom, NULL) ==
                     0,
                 error = OT_ERROR_FAILED);
    VerifyOrExit(mbedtls_mpi_size(&rMpi) + mbedtls_mpi_size(&sMpi) <= *aOutputLength, error = OT_ERROR_NO_BUFS);

    // Concatenate the two octet sequences in the order R and then S.
    VerifyOrExit(mbedtls_mpi_write_binary(&rMpi, aOutput, mbedtls_mpi_size(&rMpi)) == 0, error = OT_ERROR_FAILED);
    *aOutputLength = mbedtls_mpi_size(&rMpi);

    VerifyOrExit(mbedtls_mpi_write_binary(&sMpi, aOutput + *aOutputLength, mbedtls_mpi_size(&sMpi)) == 0,
                 error = OT_ERROR_FAILED);
    *aOutputLength += mbedtls_mpi_size(&sMpi);

exit:
    mbedtls_mpi_free(&rMpi);
    mbedtls_mpi_free(&sMpi);
    mbedtls_ecdsa_free(&ctx);
    mbedtls_pk_free(&pkCtx);

    return error;
}

int Ecdsa::FillRandom(void *, unsigned char *aBuffer, size_t aSize)
{
    Random::FillBuffer(aBuffer, aSize);

    return 0;
}

#endif // OPENTHREAD_ENABLE_ECDSA

} // namespace Crypto
} // namespace ot
<commit_msg>[ecdsa] fix -Wimplicit-int-conversion warnings (#3382)<commit_after>/*
 *  Copyright (c) 2018, The OpenThread Authors.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *  1. Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *  3. Neither the name of the copyright holder nor the
 *     names of its contributors may be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @file
 *   This file implements ECDSA signing.
 */

#include "ecdsa.hpp"

#include <mbedtls/ecdsa.h>
#include <mbedtls/pk.h>

#include "common/code_utils.hpp"
#include "common/debug.hpp"
#include "common/random.hpp"

namespace ot {
namespace Crypto {

#if OPENTHREAD_ENABLE_ECDSA

otError Ecdsa::Sign(uint8_t *      aOutput,
                    uint16_t *     aOutputLength,
                    const uint8_t *aInputHash,
                    uint16_t       aInputHashLength,
                    const uint8_t *aPrivateKey,
                    uint16_t       aPrivateKeyLength)
{
    otError               error = OT_ERROR_NONE;
    mbedtls_ecdsa_context ctx;
    mbedtls_pk_context    pkCtx;
    mbedtls_ecp_keypair * keypair;
    mbedtls_mpi           rMpi;
    mbedtls_mpi           sMpi;

    mbedtls_pk_init(&pkCtx);
    mbedtls_ecdsa_init(&ctx);
    mbedtls_mpi_init(&rMpi);
    mbedtls_mpi_init(&sMpi);

    // Parse a private key in PEM format.
    VerifyOrExit(mbedtls_pk_parse_key(&pkCtx, aPrivateKey, aPrivateKeyLength, NULL, 0) == 0,
                 error = OT_ERROR_INVALID_ARGS);
    VerifyOrExit(mbedtls_pk_get_type(&pkCtx) == MBEDTLS_PK_ECKEY, error = OT_ERROR_INVALID_ARGS);

    keypair = mbedtls_pk_ec(pkCtx);
    assert(keypair != NULL);

    VerifyOrExit(mbedtls_ecdsa_from_keypair(&ctx, keypair) == 0, error = OT_ERROR_FAILED);

    // Sign using ECDSA.
    VerifyOrExit(mbedtls_ecdsa_sign(&ctx.grp, &rMpi, &sMpi, &ctx.d, aInputHash, aInputHashLength, FillRandom, NULL) ==
                     0,
                 error = OT_ERROR_FAILED);
    VerifyOrExit(mbedtls_mpi_size(&rMpi) + mbedtls_mpi_size(&sMpi) <= *aOutputLength, error = OT_ERROR_NO_BUFS);

    // Concatenate the two octet sequences in the order R and then S.
    VerifyOrExit(mbedtls_mpi_write_binary(&rMpi, aOutput, mbedtls_mpi_size(&rMpi)) == 0, error = OT_ERROR_FAILED);
    *aOutputLength = static_cast<uint16_t>(mbedtls_mpi_size(&rMpi));

    VerifyOrExit(mbedtls_mpi_write_binary(&sMpi, aOutput + *aOutputLength, mbedtls_mpi_size(&sMpi)) == 0,
                 error = OT_ERROR_FAILED);
    *aOutputLength += mbedtls_mpi_size(&sMpi);

exit:
    mbedtls_mpi_free(&rMpi);
    mbedtls_mpi_free(&sMpi);
    mbedtls_ecdsa_free(&ctx);
    mbedtls_pk_free(&pkCtx);

    return error;
}

int Ecdsa::FillRandom(void *, unsigned char *aBuffer, size_t aSize)
{
    Random::FillBuffer(aBuffer, static_cast<uint16_t>(aSize));

    return 0;
}

#endif // OPENTHREAD_ENABLE_ECDSA

} // namespace Crypto
} // namespace ot
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2017 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <grpc/support/port_platform.h>

#include "src/core/lib/gpr/arena.h"

#include <string.h>

#include <grpc/support/alloc.h>
#include <grpc/support/atm.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>

#include "src/core/lib/gpr/alloc.h"

// Uncomment this to use a simple arena that simply allocates the
// requested amount of memory for each call to gpr_arena_alloc().  This
// effectively eliminates the efficiency gain of using an arena, but it
// may be useful for debugging purposes.
//#define SIMPLE_ARENA_FOR_DEBUGGING

#ifdef SIMPLE_ARENA_FOR_DEBUGGING

struct gpr_arena {
  gpr_mu mu;
  void** ptrs;
  size_t num_ptrs;
};

gpr_arena* gpr_arena_create(size_t ignored_initial_size) {
  gpr_arena* arena = (gpr_arena*)gpr_zalloc(sizeof(*arena));
  gpr_mu_init(&arena->mu);
  return arena;
}

size_t gpr_arena_destroy(gpr_arena* arena) {
  gpr_mu_destroy(&arena->mu);
  for (size_t i = 0; i < arena->num_ptrs; ++i) {
    gpr_free(arena->ptrs[i]);
  }
  gpr_free(arena->ptrs);
  gpr_free(arena);
  return 1;  // Value doesn't matter, since it won't be used.
}

void* gpr_arena_alloc(gpr_arena* arena, size_t size) {
  gpr_mu_lock(&arena->mu);
  arena->ptrs =
      (void**)gpr_realloc(arena->ptrs, sizeof(void*) * (arena->num_ptrs + 1));
  void* retval = arena->ptrs[arena->num_ptrs++] = gpr_zalloc(size);
  gpr_mu_unlock(&arena->mu);
  return retval;
}

#else  // SIMPLE_ARENA_FOR_DEBUGGING

// TODO(roth): We currently assume that all callers need alignment of 16
// bytes, which may be wrong in some cases.  As part of converting the
// arena API to C++, we should consider replacing gpr_arena_alloc() with a
// template that takes the type of the value being allocated, which
// would allow us to use the alignment actually needed by the caller.

typedef struct zone {
  zone* next;
} zone;

struct gpr_arena {
  gpr_atm total_used;
  gpr_atm initial_zone_used;
  size_t initial_zone_size;
  zone initial_zone;
  zone* last_zone;
  gpr_mu arena_growth_mutex;
};

static void* zalloc_aligned(size_t size) {
  void* ptr = gpr_malloc_aligned(size, GPR_MAX_ALIGNMENT);
  memset(ptr, 0, size);
  return ptr;
}

gpr_arena* gpr_arena_create(size_t initial_size) {
  initial_size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(initial_size);
  gpr_arena* a = static_cast<gpr_arena*>(zalloc_aligned(
      GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(gpr_arena)) + initial_size));
  a->initial_zone_size = initial_size;
  a->last_zone = &a->initial_zone;
  gpr_mu_init(&a->arena_growth_mutex);
  return a;
}

size_t gpr_arena_destroy(gpr_arena* arena) {
  gpr_mu_destroy(&arena->arena_growth_mutex);
  gpr_atm size = gpr_atm_no_barrier_load(&arena->total_used);
  zone* z = arena->initial_zone.next;
  gpr_free_aligned(arena);
  while (z) {
    zone* next_z = z->next;
    gpr_free_aligned(z);
    z = next_z;
  }
  return static_cast<size_t>(size);
}

void* gpr_arena_alloc(gpr_arena* arena, size_t size) {
  size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(size);
  // Update the total used size to estimate next call's size.
  gpr_atm_no_barrier_fetch_add(&arena->total_used, size);
  // Try to allocate in the initial zone.
  size_t initial_zone_alloc_begin = static_cast<size_t>(
      gpr_atm_no_barrier_fetch_add(&arena->initial_zone_used, size));
  size_t initial_zone_alloc_end = initial_zone_alloc_begin + size;
  if (initial_zone_alloc_end <= arena->initial_zone_size) {
    return reinterpret_cast<char*>(arena) +
           GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(gpr_arena)) +
           initial_zone_alloc_begin;
  } else {
    // If the allocation isn't able to end in the initial zone, create a new
    // zone for this allocation, and any unused space in the initial zone is
    // wasted. This overflowing and wasting is uncommon because of our arena
    // sizing historesis (that is, most calls should have a large enough initial
    // zone and will not need to grow the arena).
    gpr_mu_lock(&arena->arena_growth_mutex);
    zone* z = static_cast<zone*>(
        zalloc_aligned(GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(zone)) + size));
    arena->last_zone->next = z;
    arena->last_zone = z;
    gpr_mu_unlock(&arena->arena_growth_mutex);
    return reinterpret_cast<char*>(z) +
           GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(zone));
  }
}

#endif  // SIMPLE_ARENA_FOR_DEBUGGING
<commit_msg>Remove unnecessary atm<commit_after>/*
 *
 * Copyright 2017 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <grpc/support/port_platform.h>

#include "src/core/lib/gpr/arena.h"

#include <string.h>

#include <grpc/support/alloc.h>
#include <grpc/support/atm.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>

#include "src/core/lib/gpr/alloc.h"

// Uncomment this to use a simple arena that simply allocates the
// requested amount of memory for each call to gpr_arena_alloc().  This
// effectively eliminates the efficiency gain of using an arena, but it
// may be useful for debugging purposes.
//#define SIMPLE_ARENA_FOR_DEBUGGING

#ifdef SIMPLE_ARENA_FOR_DEBUGGING

struct gpr_arena {
  gpr_mu mu;
  void** ptrs;
  size_t num_ptrs;
};

gpr_arena* gpr_arena_create(size_t ignored_initial_size) {
  gpr_arena* arena = (gpr_arena*)gpr_zalloc(sizeof(*arena));
  gpr_mu_init(&arena->mu);
  return arena;
}

size_t gpr_arena_destroy(gpr_arena* arena) {
  gpr_mu_destroy(&arena->mu);
  for (size_t i = 0; i < arena->num_ptrs; ++i) {
    gpr_free(arena->ptrs[i]);
  }
  gpr_free(arena->ptrs);
  gpr_free(arena);
  return 1;  // Value doesn't matter, since it won't be used.
}

void* gpr_arena_alloc(gpr_arena* arena, size_t size) {
  gpr_mu_lock(&arena->mu);
  arena->ptrs =
      (void**)gpr_realloc(arena->ptrs, sizeof(void*) * (arena->num_ptrs + 1));
  void* retval = arena->ptrs[arena->num_ptrs++] = gpr_zalloc(size);
  gpr_mu_unlock(&arena->mu);
  return retval;
}

#else  // SIMPLE_ARENA_FOR_DEBUGGING

// TODO(roth): We currently assume that all callers need alignment of 16
// bytes, which may be wrong in some cases.  As part of converting the
// arena API to C++, we should consider replacing gpr_arena_alloc() with a
// template that takes the type of the value being allocated, which
// would allow us to use the alignment actually needed by the caller.

typedef struct zone {
  zone* next;
} zone;

struct gpr_arena {
  // Keep track of the total used size. We use this in our call sizing
  // historesis.
  gpr_atm total_used;
  size_t initial_zone_size;
  zone initial_zone;
  zone* last_zone;
  gpr_mu arena_growth_mutex;
};

static void* zalloc_aligned(size_t size) {
  void* ptr = gpr_malloc_aligned(size, GPR_MAX_ALIGNMENT);
  memset(ptr, 0, size);
  return ptr;
}

gpr_arena* gpr_arena_create(size_t initial_size) {
  initial_size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(initial_size);
  gpr_arena* a = static_cast<gpr_arena*>(zalloc_aligned(
      GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(gpr_arena)) + initial_size));
  a->initial_zone_size = initial_size;
  a->last_zone = &a->initial_zone;
  gpr_mu_init(&a->arena_growth_mutex);
  return a;
}

size_t gpr_arena_destroy(gpr_arena* arena) {
  gpr_mu_destroy(&arena->arena_growth_mutex);
  gpr_atm size = gpr_atm_no_barrier_load(&arena->total_used);
  zone* z = arena->initial_zone.next;
  gpr_free_aligned(arena);
  while (z) {
    zone* next_z = z->next;
    gpr_free_aligned(z);
    z = next_z;
  }
  return static_cast<size_t>(size);
}

void* gpr_arena_alloc(gpr_arena* arena, size_t size) {
  size = GPR_ROUND_UP_TO_ALIGNMENT_SIZE(size);
  size_t begin = gpr_atm_no_barrier_fetch_add(&arena->total_used, size);
  if (begin + size <= arena->initial_zone_size) {
    return reinterpret_cast<char*>(arena) +
           GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(gpr_arena)) + begin;
  } else {
    // If the allocation isn't able to end in the initial zone, create a new
    // zone for this allocation, and any unused space in the initial zone is
    // wasted. This overflowing and wasting is uncommon because of our arena
    // sizing historesis (that is, most calls should have a large enough initial
    // zone and will not need to grow the arena).
    gpr_mu_lock(&arena->arena_growth_mutex);
    zone* z = static_cast<zone*>(
        zalloc_aligned(GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(zone)) + size));
    arena->last_zone->next = z;
    arena->last_zone = z;
    gpr_mu_unlock(&arena->arena_growth_mutex);
    return reinterpret_cast<char*>(z) +
           GPR_ROUND_UP_TO_ALIGNMENT_SIZE(sizeof(zone));
  }
}

#endif  // SIMPLE_ARENA_FOR_DEBUGGING
<|endoftext|>


<commit_before>/*** Copyright (c), The Regents of the University of California            ***
 *** For more information please refer to files in the COPYRIGHT directory ***/
/* rsStructFileBundle.c. See structFileBundle.h for a description of
 * this API call.*/

#include "reFuncDefs.hpp"
#include "apiHeaderAll.hpp"
#include "objMetaOpr.hpp"
#include "dataObjOpr.hpp"
#include "physPath.hpp"
#include "miscServerFunct.hpp"
#include "rcGlobalExtern.hpp"
#include "reGlobalsExtern.hpp"

// =-=-=-=-=-=-=-
#include "irods_log.hpp"
#include "irods_file_object.hpp"
#include "irods_stacktrace.hpp"
#include "irods_resource_redirect.hpp"

int
rsStructFileBundle( rsComm_t *rsComm,
                    structFileExtAndRegInp_t *structFileBundleInp ) {
    int status;
    rodsServerHost_t *rodsServerHost;
    int remoteFlag;
    dataObjInp_t dataObjInp;

    memset( &dataObjInp, 0, sizeof( dataObjInp ) );
    rstrcpy( dataObjInp.objPath, structFileBundleInp->objPath,
             MAX_NAME_LEN );

    remoteFlag = getAndConnRemoteZone( rsComm, &dataObjInp, &rodsServerHost,
                                       REMOTE_CREATE );

    if ( remoteFlag < 0 ) {
        return remoteFlag;
    }
    else if ( remoteFlag == REMOTE_HOST ) {
        status = rcStructFileBundle( rodsServerHost->conn,
                                     structFileBundleInp );
        return status;
    }

    // =-=-=-=-=-=-=-
    // working on the "home zone", determine if we need to redirect to a different
    // server in this zone for this operation.  if there is a RESC_HIER_STR_KW then
    // we know that the redirection decision has already been made
    std::string       hier;
    int               local = LOCAL_HOST;
    rodsServerHost_t* host  =  0;
    dataObjInp_t      data_inp;
    bzero( &data_inp, sizeof( data_inp ) );
    rstrcpy( data_inp.objPath, structFileBundleInp->objPath, MAX_NAME_LEN );
    copyKeyValPairStruct( &structFileBundleInp->condInput, &data_inp.condInput );
    if ( getValByKey( &structFileBundleInp->condInput, RESC_HIER_STR_KW ) == NULL ) {
        irods::error ret = irods::resource_redirect( irods::CREATE_OPERATION, rsComm,
                           &data_inp, hier, host, local );
        if ( !ret.ok() ) {
            std::stringstream msg;
            msg << "rsStructFileBundle :: failed in irods::resource_redirect for [";
            msg << &data_inp.objPath << "]";
            irods::log( PASSMSG( msg.str(), ret ) );
            return ret.code();
        }

        // =-=-=-=-=-=-=-
        // we resolved the redirect and have a host, set the hier str for subsequent
        // api calls, etc.
        addKeyVal( &structFileBundleInp->condInput, RESC_HIER_STR_KW, hier.c_str() );

    } // if keyword

    if ( LOCAL_HOST == local ) {
        status = _rsStructFileBundle( rsComm, structFileBundleInp );
    }
    else {
        status = rcStructFileBundle( host->conn, structFileBundleInp );
    } // else remote host

    return status;
}

int _rsStructFileBundle( rsComm_t*                 rsComm,
                         structFileExtAndRegInp_t* structFileBundleInp ) {
    int status;
    int handleInx;
    char phyBunDir[MAX_NAME_LEN];
    char tmpPath[MAX_NAME_LEN];
    int l1descInx;
    char* dataType = 0; // JMC - backport 4664
    openedDataObjInp_t dataObjCloseInp;

    // =-=-=-=-=-=-=-
    // create an empty data obj
    dataObjInp_t dataObjInp;
    memset( &dataObjInp, 0, sizeof( dataObjInp ) );
    dataObjInp.openFlags = O_WRONLY;

    // =-=-=-=-=-=-=-
    // get the data type of the structured file
    dataType = getValByKey( &structFileBundleInp->condInput, DATA_TYPE_KW );

    // =-=-=-=-=-=-=-
    // ensure that the file name will end in .zip, if necessary
    if ( dataType != NULL && strstr( dataType, ZIP_DT_STR ) != NULL ) {
        int len = strlen( structFileBundleInp->objPath );
        if ( strcmp( &structFileBundleInp->objPath[len - 4], ".zip" ) != 0 ) {
            strcat( structFileBundleInp->objPath, ".zip" );
        }
    }

    // =-=-=-=-=-=-=-
    // capture the object path in the data obj struct
    rstrcpy( dataObjInp.objPath, structFileBundleInp->objPath, MAX_NAME_LEN );

    // =-=-=-=-=-=-=-
    // replicate the condInput. may have resource input
    replKeyVal( &structFileBundleInp->condInput, &dataObjInp.condInput );

    // =-=-=-=-=-=-=-
    // open the file if we are in an add operation, otherwise create the new file
    if ( ( structFileBundleInp->oprType & ADD_TO_TAR_OPR ) != 0 ) { // JMC - backport 4643
        l1descInx = rsDataObjOpen( rsComm, &dataObjInp );

    }
    else {
        l1descInx = rsDataObjCreate( rsComm, &dataObjInp );

    }

    // =-=-=-=-=-=-=-
    // error check create / open
    if ( l1descInx < 0 ) {
        rodsLog( LOG_ERROR, "rsStructFileBundle: rsDataObjCreate of %s error. status = %d",
                 dataObjInp.objPath, l1descInx );
        return l1descInx;
    }

    // =-=-=-=-=-=-=-
    // FIXME :: Why, when we replicate them above?
    clearKeyVal( &dataObjInp.condInput ); // JMC - backport 4637
    // ???? l3Close (rsComm, l1descInx);

    // =-=-=-=-=-=-=-
    // zip does not like a zero length file as target
    //L1desc[ l1descInx ].l3descInx = 0;
    //if( dataType != NULL && strstr( dataType, ZIP_DT_STR ) != NULL ) {
    //    if( ( structFileBundleInp->oprType & ADD_TO_TAR_OPR) == 0 ) { // JMC - backport 4643
    //        l3Unlink( rsComm, L1desc[l1descInx].dataObjInfo );
    //    }
    //}

    // =-=-=-=-=-=-=-
    // check object permissions / stat
    chkObjPermAndStat_t chkObjPermAndStatInp;
    memset( &chkObjPermAndStatInp, 0, sizeof( chkObjPermAndStatInp ) );
    rstrcpy( chkObjPermAndStatInp.objPath, structFileBundleInp->collection, MAX_NAME_LEN );
    chkObjPermAndStatInp.flags = CHK_COLL_FOR_BUNDLE_OPR;
    addKeyVal( &chkObjPermAndStatInp.condInput, RESC_NAME_KW,     L1desc[l1descInx].dataObjInfo->rescName );

    // =-=-=-=-=-=-=-
    // get the resc hier string
    std::string resc_hier;
    char* resc_hier_ptr = getValByKey( &structFileBundleInp->condInput, RESC_HIER_STR_KW );
    if ( !resc_hier_ptr ) {
        rodsLog( LOG_NOTICE, "_rsStructFileBundle :: RESC_HIER_STR_KW is NULL" );
    }
    else {
        addKeyVal( &chkObjPermAndStatInp.condInput, RESC_HIER_STR_KW, resc_hier_ptr );
        resc_hier = resc_hier_ptr;
    }

    status = rsChkObjPermAndStat( rsComm, &chkObjPermAndStatInp );
    if ( status < 0 ) {
        rodsLog( LOG_ERROR, "rsStructFileBundle: rsChkObjPermAndStat of %s error. stat = %d",
                 chkObjPermAndStatInp.objPath, status );
        dataObjCloseInp.l1descInx = l1descInx;
        rsDataObjClose( rsComm, &dataObjCloseInp );
        return status;
    }

    clearKeyVal( &chkObjPermAndStatInp.condInput );

    // =-=-=-=-=-=-=-
    // create the special hidden directory where the bundling happens
    createPhyBundleDir( rsComm, L1desc[ l1descInx ].dataObjInfo->filePath, phyBunDir, L1desc[ l1descInx ].dataObjInfo->rescHier );

    // =-=-=-=-=-=-=-
    // build a collection open input structure
    collInp_t collInp;
    bzero( &collInp, sizeof( collInp ) );
    collInp.flags = RECUR_QUERY_FG | VERY_LONG_METADATA_FG | NO_TRIM_REPL_FG | INCLUDE_CONDINPUT_IN_QUERY;
    rstrcpy( collInp.collName, structFileBundleInp->collection, MAX_NAME_LEN );
    addKeyVal( &collInp.condInput, RESC_NAME_KW, L1desc[ l1descInx ].dataObjInfo->rescName );

    rodsLog( LOG_DEBUG, "rsStructFileBundle: calling rsOpenCollection for [%s]", structFileBundleInp->collection );

    // =-=-=-=-=-=-=-
    // open the collection from which we will bundle
    handleInx = rsOpenCollection( rsComm, &collInp );
    if ( handleInx < 0 ) {
        rodsLog( LOG_ERROR, "rsStructFileBundle: rsOpenCollection of %s error. status = %d",
                 collInp.collName, handleInx );
        rmdir( phyBunDir );
        return handleInx;
    }

    // =-=-=-=-=-=-=-
    // preserve the collection path?
    int collLen = 0;
    if ( ( structFileBundleInp->oprType & PRESERVE_COLL_PATH ) != 0 ) {
        // =-=-=-=-=-=-=-
        // preserve the last entry of the coll path
        char* tmpPtr = collInp.collName;
        int   tmpLen = 0;
        collLen = 0;

        // =-=-=-=-=-=-=-
        // find length to the last '/'
        while ( *tmpPtr != '\0' ) {
            if ( *tmpPtr == '/' ) {
                collLen = tmpLen;
            }

            tmpLen++;
            tmpPtr++;
        }

    }
    else {
        collLen = strlen( collInp.collName );

    }

    // =-=-=-=-=-=-=-
    // preserve the collection path?
    collEnt_t* collEnt = NULL;
    while ( ( status = rsReadCollection( rsComm, &handleInx, &collEnt ) ) >= 0 ) {
        if ( NULL == collEnt ) { // JMC cppcheck - nullptr
            rodsLog( LOG_ERROR, "rsStructFileBundle: collEnt is NULL" );
            continue;
        }

        // =-=-=-=-=-=-=-
        // entry is a data object
        if ( collEnt->objType == DATA_OBJ_T ) {
            if ( collEnt->collName[collLen] == '\0' ) {
                snprintf(
                    tmpPath,
                    MAX_NAME_LEN,
                    "%s/%s",
                    phyBunDir,
                    collEnt->dataName );
            }
            else {
                snprintf(
                    tmpPath,
                    MAX_NAME_LEN, "%s/%s/%s",
                    phyBunDir,
                    collEnt->collName + collLen + 1,
                    collEnt->dataName );
                status = mkDirForFilePath(
                    rsComm,
                    strlen( phyBunDir ),
                    tmpPath,
                    collEnt->resc_hier,
                    getDefDirMode() );
                if ( status < 0 ) {
                    rodsLog( LOG_ERROR, "mkDirForFilePath failed in _rsStructFileBundle with status %d", status );
                    return status;
                }
            }

            // =-=-=-=-=-=-=-
            // filter out any possible replicas that are not on this resource
            if ( resc_hier == collEnt->resc_hier ) {
                // =-=-=-=-=-=-=-
                // add a link
                status = link( collEnt->phyPath, tmpPath );
                if ( status < 0 ) {
                    rodsLog( LOG_ERROR, "rsStructFileBundle: link error %s to %s. errno = %d",
                             collEnt->phyPath, tmpPath, errno );
                    rmLinkedFilesInUnixDir( phyBunDir );
                    rmdir( phyBunDir );
                    free( collEnt );
                    return UNIX_FILE_LINK_ERR - errno;
                }
                else {
                    //rodsLog( LOG_NOTICE, "_rsStructFileBundle - LINK  [%s] on resc [%s]", collEnt->phyPath, collEnt->resc_hier );
                }
            }
            else {
                //rodsLog( LOG_NOTICE, "_rsStructFileBundle - skipping [%s] on resc [%s]", collEnt->phyPath, collEnt->resc_hier );
            }
        }
        else {
            // =-=-=-=-=-=-=-
            // entry is a collection
            if ( ( int ) strlen( collEnt->collName ) + 1 <= collLen ) {
                free( collEnt );
                continue;
            }
            snprintf( tmpPath, MAX_NAME_LEN, "%s/%s", phyBunDir, collEnt->collName + collLen );
            status = mkFileDirR( rsComm, strlen( phyBunDir ), tmpPath, resc_hier.c_str(), getDefDirMode() );
            if ( status < 0 ) {
                rodsLog( LOG_ERROR, "mkFileDirR failed in _rsStructFileBundle with status %d", status );
                free( collEnt );
                return status;
            }
        } // else

        if ( collEnt != NULL ) {
            free( collEnt );
            collEnt = NULL;
        }

    } // while

    // =-=-=-=-=-=-=-
    // clean up key vals and close the collection
    clearKeyVal( &collInp.condInput );
    rsCloseCollection( rsComm, &handleInx );

    // =-=-=-=-=-=-=-
    // call the helper function to do the actual bundling
    status = phyBundle( rsComm, L1desc[l1descInx].dataObjInfo, phyBunDir,
                        collInp.collName, structFileBundleInp->oprType ); // JMC - backport 4643

    int savedStatus = 0;
    if ( status < 0 ) {
        rodsLog( LOG_ERROR, "rsStructFileBundle: phyBundle of %s error. stat = %d",
                 L1desc[ l1descInx ].dataObjInfo->objPath, status );
        L1desc[ l1descInx ].bytesWritten = 0;
        savedStatus = status;
    }
    else {
        // mark it was written so the size would be adjusted
        L1desc[ l1descInx ].bytesWritten = 1;
    }

    // =-=-=-=-=-=-=-
    // clean up after the bundle directory
    rmLinkedFilesInUnixDir( phyBunDir );
    rmdir( phyBunDir );

    dataObjCloseInp.l1descInx = l1descInx;
    status = rsDataObjClose( rsComm, &dataObjCloseInp );
    if ( status >= 0 ) {
        return savedStatus;
    }

    return status;
}

int
remoteStructFileBundle( rsComm_t *rsComm,
                        structFileExtAndRegInp_t *structFileBundleInp, rodsServerHost_t *rodsServerHost ) {
    int status;

    if ( rodsServerHost == NULL ) {
        rodsLog( LOG_NOTICE,
                 "remoteStructFileBundle: Invalid rodsServerHost" );
        return SYS_INVALID_SERVER_HOST;
    }

    if ( ( status = svrToSvrConnect( rsComm, rodsServerHost ) ) < 0 ) {
        return status;
    }

    status = rcStructFileBundle( rodsServerHost->conn, structFileBundleInp );
    return status;
}

<commit_msg>[#2212] CID25953:<commit_after>/*** Copyright (c), The Regents of the University of California            ***
 *** For more information please refer to files in the COPYRIGHT directory ***/
/* rsStructFileBundle.c. See structFileBundle.h for a description of
 * this API call.*/

#include "reFuncDefs.hpp"
#include "apiHeaderAll.hpp"
#include "objMetaOpr.hpp"
#include "dataObjOpr.hpp"
#include "physPath.hpp"
#include "miscServerFunct.hpp"
#include "rcGlobalExtern.hpp"
#include "reGlobalsExtern.hpp"

// =-=-=-=-=-=-=-
#include "irods_log.hpp"
#include "irods_file_object.hpp"
#include "irods_stacktrace.hpp"
#include "irods_resource_redirect.hpp"

int
rsStructFileBundle( rsComm_t *rsComm,
                    structFileExtAndRegInp_t *structFileBundleInp ) {
    int status;
    rodsServerHost_t *rodsServerHost;
    int remoteFlag;
    dataObjInp_t dataObjInp;

    memset( &dataObjInp, 0, sizeof( dataObjInp ) );
    rstrcpy( dataObjInp.objPath, structFileBundleInp->objPath,
             MAX_NAME_LEN );

    remoteFlag = getAndConnRemoteZone( rsComm, &dataObjInp, &rodsServerHost,
                                       REMOTE_CREATE );

    if ( remoteFlag < 0 ) {
        return remoteFlag;
    }
    else if ( remoteFlag == REMOTE_HOST ) {
        status = rcStructFileBundle( rodsServerHost->conn,
                                     structFileBundleInp );
        return status;
    }

    // =-=-=-=-=-=-=-
    // working on the "home zone", determine if we need to redirect to a different
    // server in this zone for this operation.  if there is a RESC_HIER_STR_KW then
    // we know that the redirection decision has already been made
    std::string       hier;
    int               local = LOCAL_HOST;
    rodsServerHost_t* host  =  0;
    dataObjInp_t      data_inp;
    bzero( &data_inp, sizeof( data_inp ) );
    rstrcpy( data_inp.objPath, structFileBundleInp->objPath, MAX_NAME_LEN );
    copyKeyValPairStruct( &structFileBundleInp->condInput, &data_inp.condInput );
    if ( getValByKey( &structFileBundleInp->condInput, RESC_HIER_STR_KW ) == NULL ) {
        irods::error ret = irods::resource_redirect( irods::CREATE_OPERATION, rsComm,
                           &data_inp, hier, host, local );
        if ( !ret.ok() ) {
            std::stringstream msg;
            msg << "rsStructFileBundle :: failed in irods::resource_redirect for [";
            msg << &data_inp.objPath << "]";
            irods::log( PASSMSG( msg.str(), ret ) );
            return ret.code();
        }

        // =-=-=-=-=-=-=-
        // we resolved the redirect and have a host, set the hier str for subsequent
        // api calls, etc.
        addKeyVal( &structFileBundleInp->condInput, RESC_HIER_STR_KW, hier.c_str() );

    } // if keyword

    if ( LOCAL_HOST == local ) {
        status = _rsStructFileBundle( rsComm, structFileBundleInp );
    }
    else {
        status = rcStructFileBundle( host->conn, structFileBundleInp );
    } // else remote host

    return status;
}

int _rsStructFileBundle( rsComm_t*                 rsComm,
                         structFileExtAndRegInp_t* structFileBundleInp ) {
    int status;
    int handleInx;
    char phyBunDir[MAX_NAME_LEN];
    char tmpPath[MAX_NAME_LEN];
    int l1descInx;
    char* dataType = 0; // JMC - backport 4664
    openedDataObjInp_t dataObjCloseInp;

    // =-=-=-=-=-=-=-
    // create an empty data obj
    dataObjInp_t dataObjInp;
    memset( &dataObjInp, 0, sizeof( dataObjInp ) );
    dataObjInp.openFlags = O_WRONLY;

    // =-=-=-=-=-=-=-
    // get the data type of the structured file
    dataType = getValByKey( &structFileBundleInp->condInput, DATA_TYPE_KW );

    // =-=-=-=-=-=-=-
    // ensure that the file name will end in .zip, if necessary
    if ( dataType != NULL && strstr( dataType, ZIP_DT_STR ) != NULL ) {
        int len = strlen( structFileBundleInp->objPath );
        if ( strcmp( &structFileBundleInp->objPath[len - 4], ".zip" ) != 0 ) {
            strcat( structFileBundleInp->objPath, ".zip" );
        }
    }

    // =-=-=-=-=-=-=-
    // capture the object path in the data obj struct
    rstrcpy( dataObjInp.objPath, structFileBundleInp->objPath, MAX_NAME_LEN );

    // =-=-=-=-=-=-=-
    // replicate the condInput. may have resource input
    replKeyVal( &structFileBundleInp->condInput, &dataObjInp.condInput );

    // =-=-=-=-=-=-=-
    // open the file if we are in an add operation, otherwise create the new file
    if ( ( structFileBundleInp->oprType & ADD_TO_TAR_OPR ) != 0 ) { // JMC - backport 4643
        l1descInx = rsDataObjOpen( rsComm, &dataObjInp );

    }
    else {
        l1descInx = rsDataObjCreate( rsComm, &dataObjInp );

    }

    // =-=-=-=-=-=-=-
    // error check create / open
    if ( l1descInx < 0 ) {
        rodsLog( LOG_ERROR, "rsStructFileBundle: rsDataObjCreate of %s error. status = %d",
                 dataObjInp.objPath, l1descInx );
        return l1descInx;
    }

    // =-=-=-=-=-=-=-
    // FIXME :: Why, when we replicate them above?
    clearKeyVal( &dataObjInp.condInput ); // JMC - backport 4637
    // ???? l3Close (rsComm, l1descInx);

    // =-=-=-=-=-=-=-
    // zip does not like a zero length file as target
    //L1desc[ l1descInx ].l3descInx = 0;
    //if( dataType != NULL && strstr( dataType, ZIP_DT_STR ) != NULL ) {
    //    if( ( structFileBundleInp->oprType & ADD_TO_TAR_OPR) == 0 ) { // JMC - backport 4643
    //        l3Unlink( rsComm, L1desc[l1descInx].dataObjInfo );
    //    }
    //}

    // =-=-=-=-=-=-=-
    // check object permissions / stat
    chkObjPermAndStat_t chkObjPermAndStatInp;
    memset( &chkObjPermAndStatInp, 0, sizeof( chkObjPermAndStatInp ) );
    rstrcpy( chkObjPermAndStatInp.objPath, structFileBundleInp->collection, MAX_NAME_LEN );
    chkObjPermAndStatInp.flags = CHK_COLL_FOR_BUNDLE_OPR;
    addKeyVal( &chkObjPermAndStatInp.condInput, RESC_NAME_KW,     L1desc[l1descInx].dataObjInfo->rescName );

    // =-=-=-=-=-=-=-
    // get the resc hier string
    std::string resc_hier;
    char* resc_hier_ptr = getValByKey( &structFileBundleInp->condInput, RESC_HIER_STR_KW );
    if ( !resc_hier_ptr ) {
        rodsLog( LOG_NOTICE, "_rsStructFileBundle :: RESC_HIER_STR_KW is NULL" );
    }
    else {
        addKeyVal( &chkObjPermAndStatInp.condInput, RESC_HIER_STR_KW, resc_hier_ptr );
        resc_hier = resc_hier_ptr;
    }

    status = rsChkObjPermAndStat( rsComm, &chkObjPermAndStatInp );
    if ( status < 0 ) {
        rodsLog( LOG_ERROR, "rsStructFileBundle: rsChkObjPermAndStat of %s error. stat = %d",
                 chkObjPermAndStatInp.objPath, status );
        dataObjCloseInp.l1descInx = l1descInx;
        rsDataObjClose( rsComm, &dataObjCloseInp );
        return status;
    }

    clearKeyVal( &chkObjPermAndStatInp.condInput );

    // =-=-=-=-=-=-=-
    // create the special hidden directory where the bundling happens
    createPhyBundleDir( rsComm, L1desc[ l1descInx ].dataObjInfo->filePath, phyBunDir, L1desc[ l1descInx ].dataObjInfo->rescHier );

    // =-=-=-=-=-=-=-
    // build a collection open input structure
    collInp_t collInp;
    bzero( &collInp, sizeof( collInp ) );
    collInp.flags = RECUR_QUERY_FG | VERY_LONG_METADATA_FG | NO_TRIM_REPL_FG | INCLUDE_CONDINPUT_IN_QUERY;
    rstrcpy( collInp.collName, structFileBundleInp->collection, MAX_NAME_LEN );
    addKeyVal( &collInp.condInput, RESC_NAME_KW, L1desc[ l1descInx ].dataObjInfo->rescName );

    rodsLog( LOG_DEBUG, "rsStructFileBundle: calling rsOpenCollection for [%s]", structFileBundleInp->collection );

    // =-=-=-=-=-=-=-
    // open the collection from which we will bundle
    handleInx = rsOpenCollection( rsComm, &collInp );
    if ( handleInx < 0 ) {
        rodsLog( LOG_ERROR, "rsStructFileBundle: rsOpenCollection of %s error. status = %d",
                 collInp.collName, handleInx );
        rmdir( phyBunDir );
        return handleInx;
    }

    // =-=-=-=-=-=-=-
    // preserve the collection path?
    int collLen = 0;
    if ( ( structFileBundleInp->oprType & PRESERVE_COLL_PATH ) != 0 ) {
        // =-=-=-=-=-=-=-
        // preserve the last entry of the coll path
        char* tmpPtr = collInp.collName;
        int   tmpLen = 0;
        collLen = 0;

        // =-=-=-=-=-=-=-
        // find length to the last '/'
        while ( *tmpPtr != '\0' ) {
            if ( *tmpPtr == '/' ) {
                collLen = tmpLen;
            }

            tmpLen++;
            tmpPtr++;
        }

    }
    else {
        collLen = strlen( collInp.collName );

    }

    // =-=-=-=-=-=-=-
    // preserve the collection path?
    collEnt_t* collEnt = NULL;
    while ( ( status = rsReadCollection( rsComm, &handleInx, &collEnt ) ) >= 0 ) {
        if ( NULL == collEnt ) { // JMC cppcheck - nullptr
            rodsLog( LOG_ERROR, "rsStructFileBundle: collEnt is NULL" );
            continue;
        }

        // =-=-=-=-=-=-=-
        // entry is a data object
        if ( collEnt->objType == DATA_OBJ_T ) {
            if ( collEnt->collName[collLen] == '\0' ) {
                snprintf(
                    tmpPath,
                    MAX_NAME_LEN,
                    "%s/%s",
                    phyBunDir,
                    collEnt->dataName );
            }
            else {
                snprintf(
                    tmpPath,
                    MAX_NAME_LEN, "%s/%s/%s",
                    phyBunDir,
                    collEnt->collName + collLen + 1,
                    collEnt->dataName );
                status = mkDirForFilePath(
                    rsComm,
                    strlen( phyBunDir ),
                    tmpPath,
                    collEnt->resc_hier,
                    getDefDirMode() );
                if ( status < 0 ) {
                    rodsLog( LOG_ERROR, "mkDirForFilePath failed in _rsStructFileBundle with status %d", status );
                    free( collEnt );
                    return status;
                }
            }

            // =-=-=-=-=-=-=-
            // filter out any possible replicas that are not on this resource
            if ( resc_hier == collEnt->resc_hier ) {
                // =-=-=-=-=-=-=-
                // add a link
                status = link( collEnt->phyPath, tmpPath );
                if ( status < 0 ) {
                    rodsLog( LOG_ERROR, "rsStructFileBundle: link error %s to %s. errno = %d",
                             collEnt->phyPath, tmpPath, errno );
                    rmLinkedFilesInUnixDir( phyBunDir );
                    rmdir( phyBunDir );
                    free( collEnt );
                    return UNIX_FILE_LINK_ERR - errno;
                }
                else {
                    //rodsLog( LOG_NOTICE, "_rsStructFileBundle - LINK  [%s] on resc [%s]", collEnt->phyPath, collEnt->resc_hier );
                }
            }
            else {
                //rodsLog( LOG_NOTICE, "_rsStructFileBundle - skipping [%s] on resc [%s]", collEnt->phyPath, collEnt->resc_hier );
            }
        }
        else {
            // =-=-=-=-=-=-=-
            // entry is a collection
            if ( ( int ) strlen( collEnt->collName ) + 1 <= collLen ) {
                free( collEnt );
                continue;
            }
            snprintf( tmpPath, MAX_NAME_LEN, "%s/%s", phyBunDir, collEnt->collName + collLen );
            status = mkFileDirR( rsComm, strlen( phyBunDir ), tmpPath, resc_hier.c_str(), getDefDirMode() );
            if ( status < 0 ) {
                rodsLog( LOG_ERROR, "mkFileDirR failed in _rsStructFileBundle with status %d", status );
                free( collEnt );
                return status;
            }
        } // else

        if ( collEnt != NULL ) {
            free( collEnt );
            collEnt = NULL;
        }

    } // while

    // =-=-=-=-=-=-=-
    // clean up key vals and close the collection
    clearKeyVal( &collInp.condInput );
    rsCloseCollection( rsComm, &handleInx );

    // =-=-=-=-=-=-=-
    // call the helper function to do the actual bundling
    status = phyBundle( rsComm, L1desc[l1descInx].dataObjInfo, phyBunDir,
                        collInp.collName, structFileBundleInp->oprType ); // JMC - backport 4643

    int savedStatus = 0;
    if ( status < 0 ) {
        rodsLog( LOG_ERROR, "rsStructFileBundle: phyBundle of %s error. stat = %d",
                 L1desc[ l1descInx ].dataObjInfo->objPath, status );
        L1desc[ l1descInx ].bytesWritten = 0;
        savedStatus = status;
    }
    else {
        // mark it was written so the size would be adjusted
        L1desc[ l1descInx ].bytesWritten = 1;
    }

    // =-=-=-=-=-=-=-
    // clean up after the bundle directory
    rmLinkedFilesInUnixDir( phyBunDir );
    rmdir( phyBunDir );

    dataObjCloseInp.l1descInx = l1descInx;
    status = rsDataObjClose( rsComm, &dataObjCloseInp );
    if ( status >= 0 ) {
        return savedStatus;
    }

    return status;
}

int
remoteStructFileBundle( rsComm_t *rsComm,
                        structFileExtAndRegInp_t *structFileBundleInp, rodsServerHost_t *rodsServerHost ) {
    int status;

    if ( rodsServerHost == NULL ) {
        rodsLog( LOG_NOTICE,
                 "remoteStructFileBundle: Invalid rodsServerHost" );
        return SYS_INVALID_SERVER_HOST;
    }

    if ( ( status = svrToSvrConnect( rsComm, rodsServerHost ) ) < 0 ) {
        return status;
    }

    status = rcStructFileBundle( rodsServerHost->conn, structFileBundleInp );
    return status;
}

<|endoftext|>