static int create_leading_directories(int base_len, const char *path, char **new_path, const char *conflict_suffix, int *clean) { int len = strlen(path); char buf[SEAF_PATH_MAX]; int offset = base_len, my_offset = base_len; SeafStat st; int n; memcpy (buf, path, base_len); *clean = 1; /* first create all leading directories. */ while (offset < len) { do { buf[my_offset] = path[offset]; offset++; my_offset++; } while (offset < len && path[offset] != '/'); if (offset >= len) { buf[my_offset] = 0; break; } buf[my_offset] = 0; if (seaf_stat (buf, &st) == 0 && S_ISDIR(st.st_mode)) { continue; } else if (S_ISREG(st.st_mode)) { time_t t = time(NULL); char time_buf[64]; /* It's not a clean merge if conflict path is created. */ *clean = 0; strftime(time_buf, 64, "%Y-%m-%d-%H-%M-%S", localtime(&t)); n = snprintf (&buf[my_offset], SEAF_PATH_MAX - my_offset, " (%s %s)", conflict_suffix, time_buf); my_offset += n; if (seaf_stat (buf, &st) == 0 && S_ISDIR(st.st_mode)) continue; } if (ccnet_mkdir (buf, 0777) < 0) { g_warning ("Failed to create directory %s.\n", buf); return -1; } } *new_path = g_strdup(buf); return 0; }
char * build_checkout_path (const char *worktree, const char *ce_name, int len) { int base_len = strlen(worktree); int full_len; char path[SEAF_PATH_MAX]; int offset; SeafStat st; if (!len) { g_warning ("entry name should not be empty.\n"); return NULL; } snprintf (path, SEAF_PATH_MAX, "%s/", worktree); /* first create all leading directories. */ full_len = base_len + len + 1; offset = base_len + 1; while (offset < full_len) { do { path[offset] = ce_name[offset-base_len-1]; offset++; } while (offset < full_len && ce_name[offset-base_len-1] != '/'); if (offset >= full_len) break; path[offset] = 0; if (seaf_stat (path, &st) == 0 && S_ISDIR(st.st_mode)) continue; if (ccnet_mkdir (path, 0777) < 0) { g_warning ("Failed to create directory %s.\n", path); return NULL; } } path[offset] = 0; return g_strdup(path); }
static int checkout_entry (struct cache_entry *ce, struct unpack_trees_options *o, gboolean recover_merge, const char *conflict_suffix) { int base_len = strlen(o->base); int len = ce_namelen(ce); int full_len; char path[PATH_MAX]; int offset; struct stat st; char file_id[41]; if (!len) { g_warning ("entry name should not be empty.\n"); return -1; } snprintf (path, PATH_MAX, "%s/", o->base); /* first create all leading directories. */ full_len = base_len + len + 1; offset = base_len + 1; while (offset < full_len) { do { path[offset] = ce->name[offset-base_len-1]; offset++; } while (offset < full_len && ce->name[offset-base_len-1] != '/'); if (offset >= full_len) break; path[offset] = 0; if (g_lstat (path, &st) == 0 && S_ISDIR(st.st_mode)) continue; if (ccnet_mkdir (path, 0777) < 0) { g_warning ("Failed to create directory %s.\n", path); return -1; } } path[offset] = 0; if (!S_ISDIR(ce->ce_mode)) { /* In case that we're replacing an empty dir with a file, * we need first to remove the empty dir. */ if (g_lstat (path, &st) == 0 && S_ISDIR(st.st_mode)) { if (g_rmdir (path) < 0) { g_warning ("Failed to remove dir %s: %s\n", path, strerror(errno)); /* Don't quit since we can handle conflict later. */ } } } else { /* For simplicity, we just don't checkout the empty dir if there is * already a file with the same name in the worktree. * This implies, you can't remove a file then create an empty directory * with the same name. But it's a rare requirement. */ if (g_mkdir (path, 0777) < 0) { g_warning ("Failed to create empty dir %s.\n", path); } return 0; } if (!o->reset && g_lstat (path, &st) == 0 && S_ISREG(st.st_mode) && (ce->ce_ctime.sec != st.st_ctime || ce->ce_mtime.sec != st.st_mtime)) { /* If we're recovering an interrupted merge, we don't know whether * the file was changed by checkout or by the user. So we have to * calculate the sha1 for that file and compare it with the one in * cache entry. */ if (!recover_merge || compare_file_content (path, &st, ce->sha1, o->crypt) != 0) { g_warning ("File %s is changed. Skip checking out.\n", path); return -1; } /* Recover merge and file content matches index entry. * We were interrupted before updating the index, update index * entry timestamp now. */ goto update_cache; } /* then checkout the file. */ rawdata_to_hex (ce->sha1, file_id, 20); if (seaf_fs_manager_checkout_file (seaf->fs_mgr, file_id, path, ce->ce_mode, o->crypt, conflict_suffix) < 0) { g_warning ("Failed to checkout file %s.\n", path); return -1; } update_cache: /* finally fill cache_entry info */ g_lstat (path, &st); fill_stat_cache_info (ce, &st); return 0; }
int main(int argc, char **argv) { char *config_dir; char *config_file; int c; char *name = NULL; program_name = argv[0]; config_dir = DEFAULT_CONFIG_DIR; while ((c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != EOF) { switch (c) { case 'h': usage (1); break; case 'c': config_dir = strdup(optarg); break; case 'n': name = strdup (optarg); break; case 'H': host_str = strdup (optarg); break; case 'P': port_str = strdup (optarg); break; default: usage(1); } } config_dir = ccnet_expand_path (config_dir); /* printf("[conf_dir=%s\n]", config_dir); */ SSLeay_add_all_algorithms(); if (RAND_status() != 1) { /* it should be seeded automatically */ fprintf(stderr, "PRNG is not seeded\n"); exit (1); } if (bits == 0) bits = DEFAULT_BITS; /* create peer key */ if (!name) { usage(-ERR_NAME_NULL); } if (strlen(name) < 2 || strlen (name) > 16 || !is_valid_username(name)) { fprintf (stderr, "The user name should be more than 2 bytes and less than 16 bytes, only digits, alphabetes and '-', '_' are allowed"); exit(-ERR_NAME_INVALID); } user_name = name; peer_name = g_strdup (name); create_peerkey (); peer_id = id_from_pubkey (peer_pubkey); identity_file_peer = g_build_filename (config_dir, PEER_KEYFILE, NULL); /* create dir */ if (ccnet_mkdir(config_dir, 0700) < 0) { fprintf (stderr, "Make dir %s error: %s\n", config_dir, strerror(errno)); exit(-ERR_PERMISSION); } /* save key */ save_privkey (peer_privkey, identity_file_peer); /* make configure file */ config_file = g_build_filename (config_dir, CONFIG_FILE_NAME, NULL); make_configure_file (config_file); printf ("Successly create configuration dir %s.\n", config_dir); exit(0); }