Exemple #1
0
/**
 * Perform FILEINFO processing specific to a regular file in sync mode
 * Returns 1 if a COMPLETE was sent in response, 0 otherwise
 */
int handle_fileinfo_sync(struct group_list_t *group)
{
    stat_struct statbuf;

    if (lstat_func(group->fileinfo.filepath, &statbuf) != -1) {
        // If source is newer, skip
        // If source is older, overwrite
        // If timestamps same, skip if sizes are also same
        int skip;
        if (group->fileinfo.tstamp < statbuf.st_mtime) {
            skip = 1;
        } else if (group->fileinfo.tstamp > statbuf.st_mtime) {
            skip = 0;
        } else if (S_ISREG(statbuf.st_mode) &&
                   (statbuf.st_size == group->fileinfo.size)) {
            skip = 1;
        } else {
            skip = 0;
        }
        if (skip) {
            glog2(group, "skipping file, in sync");
            early_complete(group, COMP_STAT_SKIPPED, 0);
            return 1;
        } else {
            glog2(group, "overwriting out of sync file");
            group->fileinfo.comp_status = COMP_STAT_OVERWRITE;
            if (group->sync_preview) {
                glog2(group, "Sync preview mode, skipping receive");
                early_complete(group, COMP_STAT_OVERWRITE, 0);
                return 1;
            }
            if (!tempfile) {
                move_to_backup(group);
            }
        }
    } else {
        glog2(group, "copying new file");
        if (group->sync_preview) {
            glog2(group, "Sync preview mode, skipping receive");
            early_complete(group, COMP_STAT_NORMAL, 0);
            return 1;
        }
        if (!tempfile) {
            move_to_backup(group);
        }
    }
    return 0;
}
Exemple #2
0
/**
 * Perform FILEINFO processing specific to a delete command
 */
void handle_fileinfo_delete(struct group_list_t *group)
{
    if (!group->sync_preview) {
        move_to_backup(group);
    }
    early_complete(group, COMP_STAT_NORMAL, 0);
}
Exemple #3
0
/**
 * Process an incoming FILEINFO message.
 * Expected in the middle of a group with no current file.
 */
void handle_fileinfo(struct group_list_t *group, const unsigned char *message,
                     unsigned meslen, struct timeval rxtime)
{
    stat_struct statbuf;
    int found_dir;

    if (!read_fileinfo(group, message, meslen, rxtime)) {
        return;
    }

    glog2(group, "Name of file to receive: %s", group->fileinfo.name);
    switch (group->fileinfo.ftype) {
    case FTYPE_REG:
        glog2(group, "Bytes: %s, Blocks: %d, Sections: %d",
                     printll(group->fileinfo.size),
                     group->fileinfo.blocks, group->fileinfo.sections);
        glog3(group, "small section size: %d, "
                     "big section size: %d, # big sections: %d",
                     group->fileinfo.secsize_small, group->fileinfo.secsize_big,
                     group->fileinfo.big_sections);
        break;
    case FTYPE_DIR:
        glog2(group, "Empty directory");
        break;
    case FTYPE_LINK:
        glog2(group, "Symbolic link to %s", group->fileinfo.linkname);
        break;
    case FTYPE_DELETE:
        glog2(group, "Deleting file/directory");
        break;
    case FTYPE_FREESPACE:
        glog2(group, "Get free space for path");
        break;
    default:
        glog1(group, "Invalid file type: %d", group->fileinfo.ftype);
        send_abort(group, "Invalid file type");
        return;
    }

    if (!setup_dest_file(group)) {
        // A rejected file is still a success because we responded with a
        // COMPLETE with status=rejected instead of with an ABORT
        return;
    }

    // Make sure the path to the destination file exists and
    // remove or back up any existing file
    if (!create_path_to_file(group, group->fileinfo.filepath)) {
        glog0(group, "Error creating path to data file");
        early_complete(group, COMP_STAT_REJECTED, 0);
        return;
    }
    found_dir = 0;
    if (tempfile && !group->sync_preview) {
        clear_path(group->fileinfo.temppath, group);
    }
    if ((group->fileinfo.ftype != FTYPE_DELETE) ||
            (group->fileinfo.ftype != FTYPE_FREESPACE)) {
        // Don't do path checks for metafile commands
    } else if (lstat_func(group->fileinfo.filepath, &statbuf) != -1) {
        glog3(group, "checking existing file");
        if ((group->fileinfo.ftype != FTYPE_DIR) || !S_ISDIR(statbuf.st_mode)) {
            if ((group->fileinfo.ftype != FTYPE_REG) ||
                    !S_ISREG(statbuf.st_mode) ||
                    ((!group->restart) && (!group->sync_mode))) {
                // Don't clear/backup if we're receiving a regular file
                // and we're in either restart mode or sync mode
                glog3(group, "calling move_to_backup");
                if (!tempfile) {
                    move_to_backup(group);
                }
            }
        } else {
            glog3(group, "found dir");
            found_dir = 1;
        }
    } else if (errno != ENOENT) {
        gsyserror(group, "Error checking file %s",group->fileinfo.filepath);
    }

    switch (group->fileinfo.ftype) {
    case FTYPE_REG:
        handle_fileinfo_regular(group);
        break;
    case FTYPE_DIR:
        handle_fileinfo_dir(group, found_dir);
        break;
    case FTYPE_LINK:
        handle_fileinfo_link(group);
        break;
    case FTYPE_DELETE:
        handle_fileinfo_delete(group);
        break;
    case FTYPE_FREESPACE:
        handle_fileinfo_freespace(group);
        break;
    default:
        glog0(group, "Error handling FILEINFO: shouldn't get here!");
    }
}
Exemple #4
0
/**
 * 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;
    }
}
Exemple #5
0
/**
 * 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;
    }
}