Ejemplo n.º 1
0
int makedevpath(int index){
    usbdevice* kb = keyboard + index;
    // Create the control path
    char path[strlen(devpath) + 2];
    snprintf(path, sizeof(path), "%s%d", devpath, index);
    if(rm_recursive(path) != 0 && errno != ENOENT){
        printf("Error: Unable to delete %s: %s\n", path, strerror(errno));
        return -1;
    }
    if(mkdir(path, S_READDIR) != 0){
        rm_recursive(path);
        printf("Error: Unable to create %s: %s\n", path, strerror(errno));
        return -1;
    }
    // Create command FIFO
    char fifopath[sizeof(path) + 4];
    snprintf(fifopath, sizeof(fifopath), "%s/cmd", path);
    if(mkfifo(fifopath, S_READWRITE) != 0 || (kb->fifo = open(fifopath, O_RDONLY | O_NONBLOCK)) <= 0){
        rm_recursive(path);
        printf("Error: Unable to create %s: %s\n", fifopath, strerror(errno));
        return -1;
    }
    if(kb->model == -1){
        // Root keyboard: write a list of devices
        updateconnected();
    } else {
        // Write the model and serial to files (doesn't apply to root keyboard)
        char mpath[sizeof(path) + 6], spath[sizeof(path) + 7];
        snprintf(mpath, sizeof(mpath), "%s/model", path);
        snprintf(spath, sizeof(spath), "%s/serial", path);
        FILE* mfile = fopen(mpath, "w");
        if(mfile){
            fputs(kb->name, mfile);
            fputc('\n', mfile);
            fclose(mfile);
            chmod(mpath, S_READ);
        } else {
            printf("Warning: Unable to create %s: %s\n", mpath, strerror(errno));
        }
        FILE* sfile = fopen(spath, "w");
        if(sfile){
            fputs(kb->setting.serial, sfile);
            fputc('\n', sfile);
            fclose(sfile);
            chmod(spath, S_READ);
        } else {
            printf("Warning: Unable to create %s: %s\n", spath, strerror(errno));
        }
    }
    return 0;
}
Ejemplo n.º 2
0
Archivo: rm.c Proyecto: jvesely/helenos
static unsigned int rm_recursive_not_empty_dirs(const char *path)
{
	DIR *dirp;
	struct dirent *dp;
	char buff[PATH_MAX];
	unsigned int scope;
	unsigned int ret = 0;

	dirp = opendir(path);
	if (!dirp) {
		/* May have been deleted between scoping it and opening it */
		cli_error(CL_EFAIL, "Could not open %s", path);
		return ret;
	}

	memset(buff, 0, sizeof(buff));
	while ((dp = readdir(dirp))) {
		snprintf(buff, PATH_MAX - 1, "%s/%s", path, dp->d_name);
		scope = rm_scope(buff);
		switch (scope) {
		case RM_BOGUS:
			break;
		case RM_FILE:
			ret += rm_single(buff);
			break;
		case RM_DIR:
			ret += rm_recursive(buff);
			break;
		}
	}

	closedir(dirp);
	
	return ret;
}
Ejemplo n.º 3
0
/**
 *
 * 恢复到历史 #id,并将恢复后的文件列表存入 file_list
 * 如果恢复发生错误,则返回空字符串,否则返回恢复的目录路径
 *
 */
std::string begin_restore(const std::string &prj, size_t id, std::list<file_info> *file_list)
{
    std::string base = prj + "/tmp";
    size_t count;
    size_t index;
    size_t full_id; //最近一次完整备份的 ID

    file_list->clear();
    rm_recursive(base);
    if(mkdir(base.c_str(), 0775) < 0)
        return std::string();
    count = get_history_qty(prj);
    if(id >= count)
        return std::string();
    if(count > 0 && id == count - 1) //如果是最近一次的历史,则直接返回 current 目录中的文件
    {
        scan(prj.c_str(), file_list);
        return prj + "/current";
    }

    index = 0;
    //寻找最近一次完整备份
    if(find_prev_full_bak(prj, id, &full_id))
    {
        if(id == full_id)
        {
            //要恢复的历史刚好是完整备份,直接返回
            std::string path;

            path = prj + "/history/" + size2string(id) + "/full";
            _scan_dir(path + "/", std::string(), file_list);
            return path;
        }
        else
        {
            //先将完整备份复制到 tmp 目录下
            bool ok;

            ok = link_or_copy_recursive(prj + "/history/" + size2string(full_id) + "/full",
                                        base);
            if(ok)
                index = full_id + 1;
            else
                return std::string();
        }
    }

    for(; index <= id; ++index)
    {
        if(!_restore(prj, base, prj + "/history/" + size2string(index)))
            return std::string();
    }
    _scan_dir(base + "/", std::string(), file_list);
    return base;
}
Ejemplo n.º 4
0
//将增量备份历史转换为完整备份
//暂时只能将最新的历史转换为完整备份
bool incremental_to_full(const std::string &prj, size_t index)
{
    std::list<file_info> patch_list;
    std::list<file_info> addition_list;
    std::string history_path;
    std::list<file_info> full_list;
    std::list<file_info>::iterator iter;
    std::string dest_dir;
    std::string dest_path;
    int fd;

    //step 1: copy files from "current/" to "history/#/full/"

    history_path = prj + "/history/" + size2string(index);
    dest_path = history_path + "/full";
    dest_dir = dest_path + "/";
    rm_recursive(dest_path);
    mkdir(dest_path.c_str(), 0755);
    ffstorage::scan(prj.c_str(), &full_list);
    for(iter = full_list.begin(); iter != full_list.end(); ++iter)
    {
        bool ok;

        if(iter->type == 'f')
            ok = link_or_copy(prj + "/current/" + iter->path, dest_dir + iter->path);
        else if(iter->type == 'd')
            ok = (0 == mkdir((dest_dir + iter->path).c_str(), 0775));
        else
            ok = false;
        if(!ok)
            goto fail;
    }
    fd = creat((history_path + "/full.done").c_str(), 0664);
    if(fd == -1)
        goto fail;
    close(fd);

    //step 2: remove incremental files (including patches)
    if(!_read_list(history_path + "/patch_list", &patch_list))
        goto fail;
    if(!_read_list(history_path + "/addition_list", &addition_list))
        goto fail;
    for(size_t i = 0; i < patch_list.size(); ++i)
        rm_recursive(history_path + "/patch." + size2string(i));
    for(size_t i = 0; i < addition_list.size(); ++i)
        //files of 'd' type are not exist
        rm_recursive(history_path + "/" + size2string(i));
    rm_recursive(history_path + "/addition_list");
    rm_recursive(history_path + "/deletion_list");
    rm_recursive(history_path + "/patch_list");

    return true;
fail:
    rm_recursive(dest_path);
    return false;
}
Ejemplo n.º 5
0
/* 准备好一个项目,创建必须的文件和目录 */
bool prepare(const char *project_name)
{
    std::string path;

    path.assign(project_name);

    rm_recursive(path + "/cache");
    mkdir((path + "/current").c_str(), 0775);
    mkdir((path + "/cache").c_str(), 0775);
    mkdir((path + "/cache/rc").c_str(), 0775);
    mkdir((path + "/history").c_str(), 0775);
    return true;
}
Ejemplo n.º 6
0
int rm_recursive(const char* path){
    DIR* dir = opendir(path);
    if(!dir)
        return remove(path);
    struct dirent* file;
    while((file = readdir(dir)))
    {
        if(!strcmp(file->d_name, ".") || !strcmp(file->d_name, ".."))
            continue;
        char path2[FILENAME_MAX];
        snprintf(path2, FILENAME_MAX, "%s/%s", path, file->d_name);
        int stat = rm_recursive(path2);
        if(stat != 0)
            return stat;
    }
    closedir(dir);
    return remove(path);
}
Ejemplo n.º 7
0
Archivo: rm.c Proyecto: jvesely/helenos
/* Main entry point for rm, accepts an array of arguments */
int cmd_rm(char **argv)
{
	unsigned int argc;
	unsigned int i, scope, ret = 0;
	int c, opt_ind;
	size_t len;
	char *buff = NULL;

	argc = cli_count_args(argv);

	if (argc < 2) {
		cli_error(CL_EFAIL,
			"%s: insufficient arguments. Try %s --help", cmdname, cmdname);
		return CMD_FAILURE;
	}

	if (!rm_start(&rm)) {
		cli_error(CL_ENOMEM, "%s: could not initialize", cmdname);
		rm_end(&rm);
		return CMD_FAILURE;
	}

	for (c = 0, optreset = 1, optind = 0, opt_ind = 0; c != -1;) {
		c = getopt_long(argc, argv, "hvrfs", long_options, &opt_ind);
		switch (c) {
		case 'h':
			help_cmd_rm(HELP_LONG);
			return CMD_SUCCESS;
		case 'v':
			printf("%s\n", RM_VERSION);
			return CMD_SUCCESS;
		case 'r':
			rm.recursive = 1;
			break;
		case 'f':
			rm.force = 1;
			break;
		case 's':
			rm.safe = 1;
			break;
		}
	}

	if ((unsigned) optind == argc) {
		cli_error(CL_EFAIL,
			"%s: insufficient arguments. Try %s --help", cmdname, cmdname);
		rm_end(&rm);
		return CMD_FAILURE;
	}

	i = optind;
	while (NULL != argv[i]) {
		len = str_size(argv[i]) + 2;
		buff = (char *) realloc(buff, len);
		if (buff == NULL) {
			printf("rm: out of memory\n");
			ret = 1;
			break;
		}
		memset(buff, 0, len);
		snprintf(buff, len, "%s", argv[i]);

		scope = rm_scope(buff);
		switch (scope) {
		case RM_BOGUS: /* FIXME */
		case RM_FILE:
			ret += rm_single(buff);
			break;
		case RM_DIR:
			if (! rm.recursive) {
				printf("%s is a directory, use -r to remove it.\n", buff);
				ret ++;
			} else {
				ret += rm_recursive(buff);
			}
			break;
		}
		i++;
	}

	if (NULL != buff)
		free(buff);

	rm_end(&rm);

	if (ret)
		return CMD_FAILURE;
	else
		return CMD_SUCCESS;
}
Ejemplo n.º 8
0
/**
 *
 * 检查、修复 corruption
 *
 * (1) /history/#/info 完整:如果 /cache 目录存在,删除掉即可
 * (2) /history/#/info 不完整:此时并未发生 corruption,重写 info 文件即可
 * (3) /history/#/info 不存在:此时可能发生 corruption,必须重新备份一次
 *
 */
void storage_check()
{
    size_t id;
    std::string history_path;
    std::list<std::string> prj_list;
    std::list<std::string>::iterator prj;
    size_t index;
    std::list<file_info>::iterator iter;
    std::list<file_info> patch_list;
    std::list<file_info> deletion_list;
    std::list<file_info> addition_list;

    fprintf(stderr, "storage checking started\n");
    prj_list = ffstorage::get_project_list();
    for(prj = prj_list.begin(); prj != prj_list.end(); ++prj)
    {
        struct stat buf;

        //删除残留的锁文件
        rm_recursive(*prj + "/lock.0");
        rm_recursive(*prj + "/lock.1");

        id = ffstorage::get_history_qty(*prj);
        if(id == 0)
            continue;
        --id;

        fprintf(stderr, "checking %s : ", prj->c_str());
        fflush(stderr);

        history_path = *prj + "/history/" + size2string(id);
        if(lstat((history_path + "/info").c_str(), &buf) == 0)
        {
            if(S_ISREG(buf.st_mode) && buf.st_size == 4)
            {
                //info 完整,对应于(1)
                if(lstat((*prj + "/cache").c_str(), &buf) == 0)
                    rm_recursive(*prj + "/cache");
                fprintf(stderr, "OK\n");
            }
            else
            {
                write_info(*prj, id); //info 存在但不完整,对应于(2)
                fprintf(stderr, "history information repaired\n");
            }
            continue;
        }

        //info 不存在,对应于(3)
        fprintf(stderr, "corruption detected");
        fflush(stderr);

        if(lstat((history_path + "/full").c_str(), &buf) == 0)
        {
            if(lstat((history_path + "/full.done").c_str(), &buf) == 0)
            {
                //此时,已经转换为完整备份,可以删掉多余的增量文件
            }
            else
            {
                //full.done 不存在,直接删除 full
                //TODO: 也可以重新转换为完整备份
                rm_recursive(history_path + "/full");
            }
            goto final;
        }

        _read_list(history_path + "/patch_list", &patch_list);
        _read_list(history_path + "/deletion_list", &deletion_list);
        _read_list(history_path + "/addition_list", &addition_list);

        //将 patch 后的文件移动到 current 目录中
        index = 0;
        for(iter = patch_list.begin(); iter != patch_list.end(); ++iter)
        {
            rename((history_path + "/rc/" + size2string(index)).c_str(),
                   (*prj + "/current/" + iter->path).c_str());
            ++index;
        }
        rmdir((history_path + "/rc").c_str());
        //递归删除列表中的文件
        for(iter = deletion_list.begin(); iter != deletion_list.end(); ++iter)
            rm_recursive(*prj + "/current/" + iter->path);
        //将新增的文件复制到相应目录下
        index = 0;
        for(iter = addition_list.begin(); iter != addition_list.end(); ++iter)
        {
            if(iter->type == 'f')
                link_or_copy(history_path + "/" + size2string(index),
                          *prj + "/current/" + iter->path);
            else if(iter->type == 'd')
                mkdir((*prj + "/current/" + iter->path).c_str(), 0775);
            ++index;
        }

final:
        ffstorage::write_info(*prj, id);
        fprintf(stderr, ", repaired\n");
    }
Ejemplo n.º 9
0
void end_restore(const std::string &prj)
{
    rm_recursive(prj + "/tmp");
}
Ejemplo n.º 10
0
bool _restore(const std::string &project_name,
              const std::string &storage_path, const std::string &history_path)
{
    std::list<file_info> patch_list;
    std::list<file_info> deletion_list;
    std::list<file_info> addition_list;
    std::list<file_info>::iterator iter;
    size_t index;

    if(!_read_list(history_path + "/patch_list", &patch_list))
        return false;
    if(!_read_list(history_path + "/deletion_list", &deletion_list))
        return false;
    if(!_read_list(history_path + "/addition_list", &addition_list))
        return false;

    //rsync patch
    index = 0;
    for(iter = patch_list.begin(); iter != patch_list.end(); ++iter)
    {
        std::string basis;
        std::string patch;
        std::string output;

        basis = storage_path + "/" + iter->path;
        patch = history_path + "/patch." + size2string(index);
        output = project_name + "/tmp_ffbackup";
        if(rsync_patch(basis, patch, output) == false)
        {
            rm_recursive(output);
            return false;
        }
        if(rename(output.c_str(), basis.c_str()) < 0)
        {
            rm_recursive(output);
            return false;
        }
        ++index;
    }

    //process deletion list
    for(iter = deletion_list.begin(); iter != deletion_list.end(); ++iter)
    {
        rm_recursive(storage_path + "/" + iter->path);
    }

    //process addition list
    index = 0;
    for(iter = addition_list.begin(); iter != addition_list.end(); ++iter)
    {
        std::string path(storage_path + "/" + iter->path);
        bool ok;

        if(iter->type == 'f')
            ok = link_or_copy(history_path + "/" + size2string(index), path);
        else if(iter->type == 'd')
            ok = (0 == mkdir(path.c_str(), 0775));
        else
            ok = false;
        if(!ok)
            return false;
        ++index;
    }
    return true;
}