FILE *store_open_file(const char *file, const char *mode) { char path[PATH_MAX]; FILE *stream; sprintf(path, "%s/%s", store_dir(), file); stream = fopen(path, mode); return stream; }
static sqlite3 *sql_handle(void) { char path[PATH_MAX]; int rc; if (_sql_handle != NULL) return _sql_handle; sprintf(path, "%s/sql.db", store_dir()); rc = sqlite3_open(path, &_sql_handle); if (rc) { logmsg("can't open database '%s': %s\n", path, sqlite3_errmsg(_sql_handle)); sqlite3_close(_sql_handle); _sql_handle = NULL; } return _sql_handle; }
static int store_st(struct DEDUPE_STORE_CONTEXT *context, struct stat st, const char* s) { if (S_ISREG(st.st_mode)) { print_stat(context, 'f', st, s); return store_file(context, st, s); } else if (S_ISDIR(st.st_mode)) { print_stat(context, 'd', st, s); fprintf(context->output_manifest, "\n"); return store_dir(context, st, s); } else if (S_ISLNK(st.st_mode)) { print_stat(context, 'l', st, s); return store_link(context, st, s); } else { fprintf(stderr, "Skipping special: %s\n", s); return 0; } }
int store_delete_file(const char *file) { char path[PATH_MAX]; sprintf(path, "%s/%s", store_dir(), file); return unlink(path); }
int dedupe_main(int argc, char** argv) { if (argc < 3) { usage(argv); return 1; } if (strcmp(argv[1], "c") == 0) { if (argc < 5) { usage(argv); return 1; } struct stat st; int ret; if (0 != (ret = lstat(argv[2], &st))) { fprintf(stderr, "Error opening input_file/input_directory.\n"); return ret; } if (!S_ISDIR(st.st_mode)) { fprintf(stderr, "%s must be a directory.\n", argv[2]); return 1; } struct DEDUPE_STORE_CONTEXT context; context.output_manifest = fopen(argv[4], "wb"); fprintf(context.output_manifest, "dedupe\t%d\n", DEDUPE_VERSION); if (context.output_manifest == NULL) { fprintf(stderr, "Unable to open output file %s\n", argv[4]); return 1; } mkdir(argv[3], S_IRWXU | S_IRWXG | S_IRWXO); realpath(argv[3], context.blob_dir); chdir(argv[2]); context.excludes = argv + 5; context.exclude_count = argc - 5; return store_dir(&context, st, "."); } else if (strcmp(argv[1], "x") == 0) { if (argc != 5) { usage(argv); return 1; } FILE *input_manifest = fopen(argv[2], "rb"); if (input_manifest == NULL) { fprintf(stderr, "Unable to open input manifest %s\n", argv[2]); return 1; } char blob_dir[PATH_MAX]; char *output_dir = argv[4]; realpath(argv[3], blob_dir); printf("%s\n" , output_dir); mkdir(output_dir, S_IRWXU | S_IRWXG | S_IRWXO); if (chdir(output_dir)) { fprintf(stderr, "Unable to open output directory %s\n", output_dir); return 1; } char line[PATH_MAX]; fgets(line, PATH_MAX, input_manifest); int version = 1; if (sscanf(line, "dedupe\t%d", &version) != 1) { fseek(input_manifest, 0, SEEK_SET); } if (version > DEDUPE_VERSION) { fprintf(stderr, "Attempting to restore newer dedupe file: %s\n", argv[2]); return 1; } while (fgets(line, PATH_MAX, input_manifest)) { //printf("%s", line); char type[4]; char mode[8]; char uid[32]; char gid[32]; char at[32]; char mt[32]; char ct[32]; char filename[PATH_MAX]; char *token = line; token = tokenize(type, token, '\t'); token = tokenize(mode, token, '\t'); token = tokenize(uid, token, '\t'); token = tokenize(gid, token, '\t'); if (version >= 2) { token = tokenize(at, token, '\t'); token = tokenize(mt, token, '\t'); token = tokenize(ct, token, '\t'); } token = tokenize(filename, token, '\t'); int mode_oct = dec_to_oct(atoi(mode)); int uid_int = atoi(uid); int gid_int = atoi(gid); int ret; //printf("%s\t%s\t%s\t%s\t%s\t", type, mode, uid, gid, filename); printf("%s\n", filename); if (strcmp(type, "f") == 0) { char sha256[128]; token = tokenize(sha256, token, '\t'); char sizeStr[32]; token = tokenize(sizeStr, token, '\t'); int size = atoi(sizeStr); // printf("%s\t%d\n", sha256, size); char blob_file[PATH_MAX]; sprintf(blob_file, "%s/%s", blob_dir, sha256); if (ret = copy_file(blob_file, filename)) { fprintf(stderr, "Unable to copy file %s\n", filename); fclose(input_manifest); return ret; } chown(filename, uid_int, gid_int); chmod(filename, mode_oct); } else if (strcmp(type, "l") == 0) { char link[41]; token = tokenize(link, token, '\t'); // printf("%s\n", link); symlink(link, filename); // Android has no lchmod, and chmod follows symlinks //chmod(filename, mode_oct); lchown(filename, uid_int, gid_int); } else if (strcmp(type, "d") == 0) { // printf("\n"); mkdir(filename, mode_oct); chown(filename, uid_int, gid_int); chmod(filename, mode_oct); } else { fprintf(stderr, "Unknown type %s\n", type); fclose(input_manifest); return 1; } if (version >= 2) { struct timeval times[2]; times[0].tv_sec = atol(at); times[1].tv_sec = atol(mt); utimes(filename, times); } } fclose(input_manifest); return 0; } else if (strcmp(argv[1], "gc") == 0) { if (argc < 3) { usage(argv); return 1; } char blob_dir[PATH_MAX]; realpath(argv[2], blob_dir); if (check_file(blob_dir)) { fprintf(stderr, "Unable to open blobs dir: %s\n", blob_dir); return 1; } char gc_dir[PATH_MAX]; sprintf(gc_dir, "%s/%s", blob_dir, ".gc"); mkdir(gc_dir, S_IRWXU | S_IRWXG | S_IRWXO); if (check_file(gc_dir)) { fprintf(stderr, "Unable to open gc dir: %s\n", gc_dir); return 1; } char blob[PATH_MAX]; int i; int failure = 0; for (i = 3; i < argc; i++) { FILE *input_manifest = fopen(argv[i], "rb"); if (input_manifest == NULL) { fprintf(stderr, "Unable to open input manifest %s\n", argv[i]); return 1; } char line[PATH_MAX]; fgets(line, PATH_MAX, input_manifest); int version = 1; if (sscanf(line, "dedupe\t%d", &version) != 1) { fseek(input_manifest, 0, SEEK_SET); } if (version > DEDUPE_VERSION) { fprintf(stderr, "Attempting to gc newer dedupe file: %s\n", argv[2]); failure = 1; fclose(input_manifest); break; } while (fgets(line, PATH_MAX, input_manifest)) { char type[4]; char mode[8]; char uid[32]; char gid[32]; char at[32]; char mt[32]; char ct[32]; char filename[PATH_MAX]; char *token = line; token = tokenize(type, token, '\t'); token = tokenize(mode, token, '\t'); token = tokenize(uid, token, '\t'); token = tokenize(gid, token, '\t'); if (version >= 2) { token = tokenize(at, token, '\t'); token = tokenize(mt, token, '\t'); token = tokenize(ct, token, '\t'); } token = tokenize(filename, token, '\t'); int mode_oct = dec_to_oct(atoi(mode)); int uid_int = atoi(uid); int gid_int = atoi(gid); int ret; // printf("%s\n", filename); if (strcmp(type, "f") == 0) { char key[128]; token = tokenize(key, token, '\t'); char sizeStr[32]; token = tokenize(sizeStr, token, '\t'); int size = atoi(sizeStr); sprintf(blob, "%s/%s", blob_dir, key); char dst[PATH_MAX]; sprintf(dst, "%s/%s", gc_dir, key); struct stat file_info; if (stat(blob, &file_info) == 0) { // keys can have a single parent directory. make sure it exists mkdir(dirname(dst), S_IRWXU | S_IRWXG | S_IRWXO); rename(blob, dst); } } } fclose(input_manifest); } // rm -rf if (!failure) recursive_delete_skip_gc(blob_dir); // move .gc over char dst[PATH_MAX]; DIR *dp = opendir(gc_dir); if (dp == NULL) { fprintf(stderr, "Error opening directory: %s\n", gc_dir); return 1; } struct dirent *ep; while (ep = readdir(dp)) { if (strcmp(ep->d_name, ".") == 0) continue; if (strcmp(ep->d_name, "..") == 0) continue; struct stat cst; int ret; sprintf(blob, "%s/%s", gc_dir, ep->d_name); sprintf(dst, "%s/%s", blob_dir, ep->d_name); if ((ret = lstat(blob, &cst))) { fprintf(stderr, "Error opening: %s\n", ep->d_name); continue; } if (rename(blob, dst)) { fprintf(stderr, "Error moving: %s\n", ep->d_name); } } closedir(dp); return failure; } else { usage(argv); return 1; } }