// basically oauth_sign_url() from liboauth in steps.. char *oauthsign_ext (int mode, char *method, oauthparam *op, int optargc, char **optargv, int *saveargcp, char ***saveargvp) { int argc=0; char **argv = NULL; char *sign=NULL; url_to_array(&argc, &argv, mode, op->url); append_parameters(&argc, &argv, optargc, optargv); add_oauth_params_to_array(&argc, &argv, op); if (saveargvp && saveargcp) { clear_parameters(saveargcp, saveargvp); append_parameters(saveargcp, saveargvp, argc, argv); } sign=process_array(argc, argv, method, mode, op); free_array(argc,argv); return (sign); // needs to be free()d. #if 0 // cruft if (sign) { add_kv_to_array(&argc, &argv, "oauth_signature", sign); free(sign); } char *result; result = oauth_serialize_url(argc, (mode&2?1:0), argv); return (result); #endif }
int main (int argc, char *argv[]) { /* check that we were given at least one argument * (the transfer file name) */ if (argc != 2) { printf("Usage: scr_transfer <transferfile>\n"); return 1; } /* record the name of the transfer file */ scr_transfer_file = strdup(argv[1]); if (scr_transfer_file == NULL) { scr_err("scr_transfer: Copying transfer file name @ %s:%d", __FILE__, __LINE__ ); return 1; } /* initialize our tracking variables */ read_params(); /* get file io mode */ mode_t mode_file = scr_getmode(1, 1, 0); /* we cache the opened file descriptors to avoid extra opens, * seeks, and closes */ int fd_src = -1; int fd_dst = -1; char* new_file_src = NULL; char* old_file_src = NULL; char* new_file_dst = NULL; char* old_file_dst = NULL; off_t new_position = 0; off_t old_position = 0; /* start in the stopped state */ state = STOPPED; set_transfer_file_state(SCR_TRANSFER_KEY_STATE_STOP, 0); /* TODO: enable this value to be set from config file */ /* TODO: page-align this buffer for faster performance */ /* allocate our file copy buffer */ size_t bufsize = scr_file_buf_size; char* buf = malloc(bufsize); if (buf == NULL) { scr_err("scr_transfer: Failed to allocate %llu bytes for file copy buffer @ %s:%d", (unsigned long long) bufsize, __FILE__, __LINE__ ); return 1; } int nread = 0; double secs_run = 0.0; double secs_slept = 0.0; double secs_run_start = scr_seconds(); double secs_run_end = secs_run_start; double secs_last_write = secs_run_start; scr_hash* hash = scr_hash_new(); while (keep_running) { /* loop here sleeping and checking transfer file periodically * until state changes and / or some time elapses */ /* reset our timer for our last write */ double secs_remain = scr_transfer_secs; while (keep_running && (state == STOPPED || secs_remain > 0.0)) { /* remember our current state before reading transfer file */ int old_state = state; /* read the transfer file, which fills in our hash and * also updates state and bytes_per_second */ scr_hash_delete(&hash); hash = read_transfer_file(); /* compute time we should sleep before writing more data based * on bandwidth and percent of runtime limits */ if (state == RUNNING) { /* get the current time */ double secs_now = scr_seconds(); /* based on the amount we last wrote and our allocated bandwidth, * compute time we need to sleep before attempting our next write */ double secs_remain_bw = 0.0; if (nread > 0 && bytes_per_second > 0.0) { double secs_to_wait_bw = (double) nread / bytes_per_second; double secs_waited_bw = secs_now - secs_last_write; secs_remain_bw = secs_to_wait_bw - secs_waited_bw; } /* based on the percentage of time we are allowed to be running, * compute time we need to sleep before attempting our next write */ double secs_remain_runtime = 0.0; if (percent_runtime > 0.0) { /* stop the run clock, add to the run time, * and restart the run clock */ secs_run_end = secs_now; secs_run += secs_run_end - secs_run_start; secs_run_start = secs_run_end; /* compute our total time, and the time we need to sleep */ double secs_total = secs_run + secs_slept; secs_remain_runtime = secs_run / percent_runtime - secs_total; } /* take the maximum of these two values */ secs_remain = secs_remain_bw; if (secs_remain_runtime > secs_remain) { secs_remain = secs_remain_runtime; } } /* check for a state transition */ if (state != old_state) { if (state == RUNNING) { /* if we switched to RUNNING, kick out without sleeping and * reset the total run and sleep times */ secs_remain = 0.0; secs_run = 0.0; secs_slept = 0.0; } else if (state == STOPPED) { /* if we switched to STOPPED, close our files if open */ close_files(new_file_src, &fd_src, new_file_dst, &fd_dst); clear_parameters(&new_file_src, &new_file_dst, &new_position); clear_parameters(&old_file_src, &old_file_dst, &old_position); /* after closing our files, update our state in the transfer file */ set_transfer_file_state(SCR_TRANSFER_KEY_STATE_STOP, 0); } } /* assume we can sleep for the full remainder of the time */ double secs = secs_remain; /* if we're not running, always sleep for the full time */ if (state != RUNNING) { secs = scr_transfer_secs; } /* set a maximum time to sleep before we read the hash file again * (ensures some responsiveness) */ if (secs > scr_transfer_secs) { secs = scr_transfer_secs; } /* sleep if we need to */ if (secs > 0.0) { /* stop the run clock and add to the total run time */ secs_run_end = scr_seconds(); secs_run += secs_run_end - secs_run_start; /* sleep */ usleep((unsigned long) (secs * 1000000.0)); secs_slept += secs; secs_remain -= secs; /* restart the run clock */ secs_run_start = scr_seconds(); } } /* write data out */ if (state == RUNNING) { /* look for a new file to transfer */ off_t filesize = 0; find_file(hash, &new_file_src, &new_file_dst, &new_position, &filesize); /* if we got a new file, close the old one (if open), * open the new file */ if (bool_diff_files(new_file_src, old_file_src)) { /* close the old descriptor if it's open */ if (fd_src >= 0) { scr_close(old_file_src, fd_src); fd_src = -1; } /* delete the old file name if we have one */ if (old_file_src != NULL) { free(old_file_src); old_file_src = NULL; } /* reset our position counter */ old_position = 0; /* open the file and remember the filename if we have one */ if (new_file_src != NULL) { fd_src = scr_open(new_file_src, O_RDONLY); /* TODO: check for errors here */ old_file_src = strdup(new_file_src); /* TODO: check for errors here */ } } /* if we got a new file, close the old one (if open), * open the new file */ if (bool_diff_files(new_file_dst, old_file_dst)) { /* close the old descriptor if it's open */ if (fd_dst >= 0) { scr_close(old_file_dst, fd_dst); fd_dst = -1; } /* delete the old file name if we have one */ if (old_file_dst != NULL) { free(old_file_dst); old_file_dst = NULL; } /* reset our position counter */ old_position = 0; /* open the file and remember the filename if we have one */ if (new_file_dst != NULL) { fd_dst = scr_open(new_file_dst, O_RDWR | O_CREAT, mode_file); /* TODO: check for errors here */ old_file_dst = strdup(new_file_dst); /* TODO: check for errors here */ } } /* we may have the same file, but perhaps the position changed * (may need to seek) */ if (new_position != old_position) { if (fd_src >= 0) { lseek(fd_src, new_position, SEEK_SET); /* TODO: check for errors here */ } if (fd_dst >= 0) { lseek(fd_dst, new_position, SEEK_SET); /* TODO: check for errors here */ } /* remember the new position */ old_position = new_position; } /* if we have two open files, * copy a chunk from source file to destination file */ nread = 0; if (fd_src >= 0 && fd_dst >= 0) { /* compute number of bytes to read from file */ size_t count = (size_t) (filesize - new_position); if (count > bufsize) { count = bufsize; } /* read a chunk */ nread = scr_read(new_file_src, fd_src, buf, count); /* if we read data, write it out */ if (nread > 0) { /* record the time of our write */ secs_last_write = scr_seconds(); /* write the chunk and force it out with an fsync */ scr_write(new_file_dst, fd_dst, buf, nread); fsync(fd_dst); /* update our position */ new_position += (off_t) nread; old_position = new_position; /* record the updated position in the transfer file */ update_transfer_file(new_file_src, new_file_dst, new_position); } /* if we've written all of the bytes, close the files */ if (new_position == filesize) { close_files(new_file_src, &fd_src, new_file_dst, &fd_dst); clear_parameters(&new_file_src, &new_file_dst, &new_position); clear_parameters(&old_file_src, &old_file_dst, &old_position); } } else { /* TODO: we may have an error * (failed to open the source or dest file) */ /* if we found no file to transfer, move to a STOPPED state */ if (new_file_src == NULL) { state = STOPPED; set_transfer_file_state(SCR_TRANSFER_KEY_STATE_STOP, 1); } } } } /* free our file copy buffer */ if (buf != NULL) { free(buf); buf = NULL; } /* free the strdup'd tranfer file name */ if (scr_transfer_file != NULL) { free(scr_transfer_file); scr_transfer_file = NULL; } return 0; }
/* given a hash of transfer file data, look for a file which needs to * be transfered. If src file is set, try to continue with that file, * otherwise, pick the first available file */ int find_file(scr_hash* hash, char** src, char** dst, off_t* position, off_t* filesize) { int found_a_file = 0; scr_hash* files = scr_hash_get(hash, SCR_TRANSFER_KEY_FILES); if (files != NULL) { /* if we're given a file name, try to continue with that file */ if (!found_a_file && src != NULL && *src != NULL) { /* src was set, so assume dst is also set, create a dummy dst * variable to hold the string which may be strdup'd in * need_transfer call */ char* tmp_dst = NULL; if (need_transfer(files, *src, &tmp_dst, position, filesize) == SCR_SUCCESS) { /* can continue with the same file (position may have been * updated though) */ found_a_file = 1; /* free the dummy */ /* TODO: note that if destination has been updated, we're * ignoring that change */ free(tmp_dst); } else { /* otherwise, this file no longer needs transfered, * so free the strings */ clear_parameters(src, dst, position); } } /* if we still don't have a file, scan the hash and use the first * file we find */ if (!found_a_file) { scr_hash_elem* elem; for (elem = scr_hash_elem_first(files); elem != NULL; elem = scr_hash_elem_next(elem)) { /* get the filename */ char* name = scr_hash_elem_key(elem); /* check whether this file needs transfered */ if (name != NULL && need_transfer(files, name, dst, position, filesize) == SCR_SUCCESS) { /* found a file, copy its name (the destination and postion * are set in need_transfer) */ *src = strdup(name); found_a_file = 1; break; } } } } /* if we didn't find a file, set src and dst to NULL and set * position to 0 */ if (!found_a_file) { clear_parameters(src, dst, position); return SCR_FAILURE; } return SCR_SUCCESS; }