/** * The main sending function. Goes through all files/diectories specified on * the command line and initializes the group for multiple files. */ int send_files() { int i, rval, len; struct finfo_t group_info; char *dir, *base; time_t t; char path[MAXPATHNAME]; t = time(NULL); if (!showtime) fprintf(applog, "\n"); log(0, 0, "%s", VERSIONSTR); if (!showtime) clog(0, 0, "Starting at %s", ctime(&t)); if (privkey) { log(0, 0, "Loaded %d bit key with fingerprint %s", RSA_keylen(privkey) * 8, print_key_fingerprint(privkey)); } if (rate == -1) { log(0, 0, "Transfer rate: full interface speed"); } else { log(0, 0, "Transfer rate: %d Kbps (%d KB/s)", rate, rate / 8); log(0, 0, "Wait between packets: %d us", packet_wait); } memset(&group_info, 0, sizeof(struct finfo_t)); if (restart_groupid) { group_info.group_id = restart_groupid; } else { group_info.group_id = rand() & 0xFFFF; group_info.group_id |= (rand() & 0xFFFF) << 16; } group_info.deststate = calloc(destcount ? destcount : MAXDEST, sizeof(struct deststate_t)); if (group_info.deststate == NULL) { syserror(0, 0, "calloc failed!"); exit(1); } log(0, 0, "Using private multicast address %s Group ID: %08X", inet_ntoa(receive_dest.sin_addr), group_info.group_id); rval = announce_phase(&group_info); if (rval) { rval = 0; for (i = 0; i < filecount; i++) { split_path(filelist[i], &dir, &base); if (strcmp(destfname, "")) { if (filecount > 1) { len = snprintf(path, sizeof(path), "%s/%s", destfname,base); if ((len >= sizeof(path)) || (len == -1)) { log(0, 0, "Max pathname length exceeded: %s/%s", destfname, base); free(dir); free(base); continue; } rval = send_file(dir, base, path, group_info.group_id); } else { rval = send_file(dir, base, destfname, group_info.group_id); } } else { rval = send_file(dir, base, base, group_info.group_id); } free(dir); free(base); if (!rval) { break; } } if (rval) { log(0, 0, "-----------------------------"); transfer_phase(&group_info); } } if (save_fail) { write_restart_file(group_info.group_id); } free(group_info.deststate); t = time(NULL); if (!showtime) clog(0, 0, "uftp: Finishing at %s", ctime(&t)); return rval; }
/** * Clean up a group list entry. Close the file if open, * free malloc'ed structures, drop the multicast group * (if no one else is using it) and free the slot. */ void file_cleanup(int listidx, int abort) { if (group_list[listidx].fileinfo.fd >= 0) { close(group_list[listidx].fileinfo.fd); group_list[listidx].fileinfo.fd = -1; if (tempfile) { move_to_backup(listidx); if (rename(group_list[listidx].fileinfo.temppath, group_list[listidx].fileinfo.filepath) == -1) { syserror(group_list[listidx].group_id, group_list[listidx].file_id, "Couldn't rename from %s to %s", group_list[listidx].fileinfo.temppath, group_list[listidx].fileinfo.filepath); } } if (group_list[listidx].fileinfo.tstamp) { utim_buf utbuf; utbuf.actime = group_list[listidx].fileinfo.tstamp; utbuf.modtime = group_list[listidx].fileinfo.tstamp; if (utime(group_list[listidx].fileinfo.filepath, &utbuf) == -1) { syserror(group_list[listidx].group_id, group_list[listidx].file_id, "utime failed"); } } } if ((group_list[listidx].version == UFTP_V2_VER) || abort || (group_list[listidx].file_id == 0)) { if ((group_list[listidx].multi.s_addr != 0) && !other_mcast_users(listidx) && group_list[listidx].multi_join) { if (server_count > 0) { multicast_leave(listener, group_list[listidx].group_id, &group_list[listidx].multi, m_interface, interface_count, server_keys, server_count); if (has_proxy) { multicast_leave(listener, group_list[listidx].group_id, &group_list[listidx].multi, m_interface, interface_count, &proxy_info, 1); } } else { multicast_leave(listener, group_list[listidx].group_id, &group_list[listidx].multi, m_interface, interface_count, NULL, 0); } } if (group_list[listidx].serverkey) { free_RSA_key(group_list[listidx].serverkey); } if (group_list[listidx].restartinfo && (strcmp(group_list[listidx].restartinfo->name, ""))) { // We have unused restart info from the last run. // Chalk this up as a loss and delete the data file char filepath[MAXPATHNAME]; snprintf(filepath, sizeof(filepath), "%s%c_group_%08X%c%s", tempdir, PATH_SEP, group_list[listidx].group_id, PATH_SEP, group_list[listidx].restartinfo->name); unlink(filepath); } if (abort) { write_restart_file(listidx); } free(group_list[listidx].fileinfo.naklist); free(group_list[listidx].fileinfo.section_done); if (group_list[listidx].restartinfo) { free(group_list[listidx].restartinfo->naklist); free(group_list[listidx].restartinfo->section_done); free(group_list[listidx].restartinfo); } memset(&group_list[listidx], 0, sizeof(group_list[listidx])); } else { // Don't clear the file_id in case we need to respond to late DONEs group_list[listidx].phase = PHASE_MIDGROUP; set_timeout(listidx); free(group_list[listidx].fileinfo.naklist); free(group_list[listidx].fileinfo.section_done); group_list[listidx].fileinfo.naklist = NULL; group_list[listidx].fileinfo.section_done = NULL; } }
/** * Clean up a group list entry. Close the file if open, * free malloc'ed structures, drop the multicast group * (if no one else is using it) and free the slot. */ void file_cleanup(struct group_list_t *group, int abort_session) { if (group->fileinfo.fd >= 0) { glog2(group, "starting file close"); close(group->fileinfo.fd); glog2(group, "done file close"); group->fileinfo.fd = -1; if (abort_session && !strcmp(tempdir, "")) { if (tempfile) { unlink(group->fileinfo.temppath); } else { unlink(group->fileinfo.filepath); } } else { if (tempfile) { move_to_backup(group); if (rename(group->fileinfo.temppath, group->fileinfo.filepath) == -1) { gsyserror(group, "Couldn't rename from %s to %s", group->fileinfo.temppath,group->fileinfo.filepath); } } if (group->fileinfo.tstamp) { utim_buf utbuf; utbuf.actime = group->fileinfo.tstamp; utbuf.modtime = group->fileinfo.tstamp; if (utime(group->fileinfo.filepath, &utbuf) == -1) { gsyserror(group, "utime failed"); } } } } if (abort_session || (group->file_id == 0)) { if (!addr_blank(&group->multi) && !other_mcast_users(group) && group->multi_join) { if (server_count > 0) { multicast_leave(listener, group->group_id, &group->multi, m_interface, interface_count, server_keys,server_count); if (has_proxy) { multicast_leave(listener, group->group_id, &group->multi, m_interface, interface_count, &proxy_info, 1); } } else { multicast_leave(listener, group->group_id, &group->multi, m_interface, interface_count, NULL, 0); } } if (group->server_pubkey.key) { if (group->keyextype == KEYEX_ECDH_ECDSA) { free_EC_key(group->server_pubkey.ec); } else { free_RSA_key(group->server_pubkey.rsa); } } if (group->server_dhkey.key) { free_EC_key(group->server_dhkey.ec); free_EC_key(group->client_dhkey.ec); } if (group->restartinfo && (strcmp(group->restartinfo->name, ""))) { // We have unused restart info from the last run. // Chalk this up as a loss and delete the data file char filepath[MAXPATHNAME]; snprintf(filepath, sizeof(filepath), "%s%c_group_%08X%c%s", tempdir, PATH_SEP, group->group_id, PATH_SEP, group->restartinfo->name); unlink(filepath); } if (abort_session) { write_restart_file(group); } free(group->loss_history); free(group->fileinfo.naklist); free(group->fileinfo.section_done); free(group->fileinfo.cache); free(group->fileinfo.cache_status); if (group->restartinfo) { free(group->restartinfo->naklist); free(group->restartinfo->section_done); free(group->restartinfo); } memset(group, 0, sizeof(struct group_list_t)); } else { // Don't clear the file_id in case we need to respond to late DONEs if (!strcmp(tempdir, "")) { run_postreceive(group, group->fileinfo.filepath); } group->phase = PHASE_MIDGROUP; set_timeout(group, 0); free(group->fileinfo.naklist); free(group->fileinfo.section_done); free(group->fileinfo.cache); free(group->fileinfo.cache_status); group->fileinfo.naklist = NULL; group->fileinfo.section_done = NULL; group->fileinfo.cache = NULL; group->fileinfo.cache_status = NULL; } }