static char * gfs_realpath_canonical_parent(const char *path, char **abspathp) { char *e, *par_dir; const char *base; int need_free = 0; base = gfarm_path_dir_skip(path); if (base == path) par_dir = "."; else if (base == path + 1) par_dir = "/"; else { par_dir = malloc(base - path); if (par_dir == NULL) return (GFARM_ERR_NO_MEMORY); /* do not copy the last '/' */ memcpy(par_dir, path, base - path - 1); par_dir[base - path - 1] = '\0'; need_free = 1; } if (strcmp(path, par_dir) == 0) { /* this should not happen but ensures termination */ e = GFARM_ERR_NO_SUCH_OBJECT; } else e = gfs_i_realpath_canonical(par_dir, abspathp); if (need_free) free(par_dir); return (e); }
static char * gfs_dircache_modify_parent(const char *pathname) { char *e = NULL; char *parent = strdup(pathname), *b; struct gfarm_path_info pi; struct timeval now; if (parent == NULL) return (GFARM_ERR_NO_MEMORY); /* create parent directory canonic path */ for (b = (char *)gfarm_path_dir_skip(parent); b > parent && b[-1] == '/'; --b) ; *b = '\0'; /* NOTE: We don't have path_info for the root directory */ if (b > parent && (e = gfarm_metadb_path_info_get(parent, &pi)) == NULL) { gettimeofday(&now, NULL); pi.status.st_mtimespec.tv_sec = now.tv_sec; pi.status.st_mtimespec.tv_nsec = now.tv_usec * GFARM_MILLISEC_BY_MICROSEC; /* the following calls gfs_dircache_enter_path() internally */ e = gfarm_path_info_replace(parent, &pi); gfarm_path_info_free(&pi); } free(parent); return (e); }
static void register_fragment(int is_dir, char *gfarm_url, int index, int nfragments, char *hostname, char *filename, int use_file_mode, gfarm_mode_t file_mode) { char *e; int fd, fd_needs_close; char *target_url; GFS_File gf; char section[GFARM_INT32STRLEN + 1]; if (!open_file(filename, &fd, &fd_needs_close)) return; if (!use_file_mode && !get_file_mode(fd, filename, &file_mode)) goto finish; if (!is_dir) target_url = gfarm_url; else if (!concat_dir_name(gfarm_url, gfarm_path_dir_skip(filename), &target_url)) goto finish; if (nfragments == GFARM_FILE_DONTCARE && !get_nsections(target_url, &nfragments)) goto finish_url; sprintf(section, "%d", index); if (opt_force || section_does_not_exists(target_url, section)) { e = gfs_pio_create(target_url, GFARM_FILE_WRONLY|GFARM_FILE_TRUNC, file_mode, &gf); if (e != NULL) { fprintf(stderr, "%s: cannot open %s: %s\n", program_name, target_url, e); error_happened = 1; } else { if ((e = gfs_pio_set_view_index(gf, nfragments, index, hostname, 0)) != NULL) { fprintf(stderr, "%s: cannot open %s:%d: %s\n", program_name, target_url, index, e); error_happened = 1; } else { copy_file(fd, gf, target_url, section); } gfs_pio_close(gf); } } finish_url: if (target_url != gfarm_url) free(target_url); finish: if (fd_needs_close) close(fd); }
static void register_program(int is_dir, char *gfarm_url, char *section, char *hostname, char *filename, int use_file_mode, gfarm_mode_t file_mode) { char *e; int fd, fd_needs_close; char *target_url; GFS_File gf; if (!open_file(filename, &fd, &fd_needs_close)) return; if (!use_file_mode && !get_file_mode(fd, filename, &file_mode)) goto finish; if (!is_dir) target_url = gfarm_url; else if (!concat_dir_name(gfarm_url, gfarm_path_dir_skip(filename), &target_url)) goto finish; if (opt_force || section_does_not_exists(target_url, section)) { e = gfs_pio_create(target_url, GFARM_FILE_WRONLY|GFARM_FILE_TRUNC, file_mode, &gf); if (e != NULL) { fprintf(stderr, "%s: cannot open %s: %s\n", program_name, target_url, e); error_happened = 1; } else { if ((e = gfs_pio_set_view_section(gf, section, hostname, 0)) != NULL) { fprintf(stderr, "%s: cannot open %s:%s: %s\n", program_name, target_url, section, e); error_happened = 1; } else { copy_file(fd, gf, target_url, section); } gfs_pio_close(gf); } } if (target_url != gfarm_url) free(target_url); finish: if (fd_needs_close) close(fd); }
static int concat_dir_name(const char *gfarm_url, const char *base_name, char **target_url_p) { char *target_url = malloc(strlen(gfarm_url) + 1 + strlen(base_name) + 1); if (target_url == NULL) { fprintf(stderr, "%s: %s\n", program_name, GFARM_ERR_NO_MEMORY); error_happened = 1; return (0); } if (*gfarm_path_dir_skip(gfarm_url_prefix_skip(gfarm_url)) != '\0') sprintf(target_url, "%s/%s", gfarm_url, base_name); else sprintf(target_url, "%s%s", gfarm_url, base_name); *target_url_p = target_url; return (1); }
gfarm_error_t gfs_opendir_caching_internal(const char *path, GFS_Dir *dirp) { gfarm_error_t e; GFS_DirPlus dp; struct gfs_dir_caching *dir; char *p; static struct gfs_dir_ops ops = { gfs_closedir_caching_internal, gfs_readdir_caching_internal, gfs_seekdir_unimpl, gfs_telldir_unimpl }; if ((e = gfs_opendirplus(path, &dp)) != GFARM_ERR_NO_ERROR) return (e); GFARM_MALLOC(dir); if (*gfarm_path_dir_skip(path) != '\0') { GFARM_MALLOC_ARRAY(p, strlen(path) + 1 + 1); if (p != NULL) sprintf(p, "%s/", path); } else { GFARM_MALLOC_ARRAY(p, strlen(path) + 1); if (p != NULL) strcpy(p, path); } if (dir == NULL || p == NULL) { gfs_closedirplus(dp); if (dir != NULL) free(dir); if (p != NULL) free(p); return (GFARM_ERR_NO_MEMORY); } dir->super.ops = &ops; dir->dp = dp; dir->path = p; *dirp = &dir->super; return (GFARM_ERR_NO_ERROR); }
static char * remove_whole_file_or_dir(char *path, Unlink_Ops ops, void *closure, int is_recursive) { struct gfs_stat gs; char *e, cwdbuf[PATH_MAX * 2]; const char *b; gfarm_mode_t mode; b = gfarm_path_dir_skip(gfarm_url_prefix_skip(path)); if (b[0] == '.' && (b[1] == '\0' || (b[1] == '.' && b[2] == '\0'))) return ("cannot remove \'.\' or \'..\'"); e = gfs_stat(path, &gs); if (e == GFARM_ERR_NO_FRAGMENT_INFORMATION) return (ops->unlink(path, closure)); if (e != NULL) return (e); mode = gs.st_mode; gfs_stat_free(&gs); if (GFARM_S_ISREG(mode)) { e = ops->unlink(path, closure); } else if (GFARM_S_ISDIR(mode)) { if (!is_recursive) return (GFARM_ERR_IS_A_DIRECTORY); e = gfs_getcwd(cwdbuf, sizeof(cwdbuf)); if (e != NULL) return (e); e = gfs_chdir(path); if (e != NULL) return (e); remove_cwd_entries(ops, closure); e = gfs_chdir_canonical(cwdbuf); if (e != NULL) return (e); e = ops->rmdir(path, closure); } return (e); }
char * gfarm_canonical_path_for_creation(const char *gfarm_file, char **canonic_pathp) { const char *basename, *p0; char *e, *p1, *dir, *dir_canonic, *lastc, cwd[PATH_MAX + 1]; *canonic_pathp = NULL; /* cause SEGV, if return value is ignored */ /* '' or 'gfarm:' case */ if (gfarm_file[0] == '\0') { e = gfs_getcwd(cwd, sizeof(cwd)); if (e != NULL) return (e); p0 = cwd; } else p0 = gfarm_file; /* Expand '~'. */ e = gfarm_path_expand_home(p0, &p1); if (e != NULL) return (e); /* Eliminate unnecessary '/'s following the basename. */ lastc = &p1[strlen(p1) - 1]; if (*lastc == '/') { while (p1 < lastc && *lastc == '/') --lastc; if (p1 == lastc) { /* * In this case, given gfarm_file is '/' or contains * only several '/'s. This means to attempt to create * the root directory. Because the root directory * should exist, the attempt will fail with the error * of 'already exist'. However, this case such that * the canonical name is "" causes many problems. * That is why the error of 'already exist' is * returned here. */ free(p1); return (GFARM_ERR_ALREADY_EXISTS); } else { *(lastc + 1) = '\0'; } } basename = gfarm_path_dir_skip(p1); if (basename == p1) /* "filename" */ dir = "."; else if (basename == p1 + 1) /* "/filename" */ dir = "/"; else { /* /.../.../filename */ p1[basename - 1 - p1] = '\0'; dir = p1; } /* Check the existence of the parent directory. */ e = gfarm_canonical_path(dir, &dir_canonic); if (e != NULL) goto free_p1; /* * check whether parent directory is writable or not. * XXX this isn't enough yet, due to missing X-bits check. */ if (dir_canonic[0] != '\0') { /* XXX "/" is always OK for now */ struct gfarm_path_info pi; e = gfarm_path_info_get(dir_canonic, &pi); if (e != NULL) goto free_dir_canonic; e = gfarm_path_info_access(&pi, GFS_W_OK); gfarm_path_info_free(&pi); if (e != NULL) goto free_dir_canonic; } *canonic_pathp = malloc(strlen(dir_canonic) + 1 + strlen(basename) + 1); if (*canonic_pathp == NULL) { e = GFARM_ERR_NO_MEMORY; goto free_dir_canonic; } /* * When the 'dir_canonic' is a null string, *canonic_pathp * will start with '/' incorrectly. */ if (dir_canonic[0] == '\0') strcpy(*canonic_pathp, basename); else sprintf(*canonic_pathp, "%s/%s", dir_canonic, basename); e = NULL; free_dir_canonic: free(dir_canonic); free_p1: free(p1); return (e); }
int try_to_make_parent_dir(char *pathname) { char *e, *p, *parent, *dirbuf; int rv, dirlen; gfarm_mode_t mode; struct stat st; struct gfarm_path_info pi; parent = strdup(pathname); if (parent == NULL) /* give up */ return (0); /* get parent directory */ p = (char *)gfarm_path_dir_skip(parent); while (p > parent && p[-1] == '/') *--p = '\0'; if (p == parent) { /* no directory part */ free(parent); return (0); } if (stat(parent, &st) == 0) { /* parent directory already exists */ free(parent); return (0); } dirbuf = strdup(parent); if (dirbuf == NULL) { free(parent); return (0); } for (dirlen = 0;;) { dirlen += strcspn(parent + dirlen, "/"); memcpy(dirbuf, parent, dirlen); dirbuf[dirlen] = '\0'; if (stat(dirbuf, &st) == 0) { if (!S_ISDIR(st.st_mode)) { free(dirbuf); free(parent); return (0); } } else { e = gfarm_path_info_get(dirbuf, &pi); mode = pi.status.st_mode; if (e != NULL || !GFARM_S_ISDIR(mode)) { if (e == NULL) gfarm_path_info_free(&pi); free(dirbuf); free(parent); return (0); } mode &= GFARM_S_ALLPERM; if (strcmp(pi.status.st_user, gfarm_get_global_username()) != 0) { mode |= 0777; } gfarm_path_info_free(&pi); rv = mkdir(dirbuf, mode); if (rv == -1) { free(dirbuf); free(parent); return (0); } } dirlen += strspn(parent + dirlen, "/"); if (parent[dirlen] == '\0') { /* OK, made */ free(dirbuf); free(parent); return (1); } } }
char * gfs_i_realpath_canonical(const char *path, char **abspathp) { struct node *n, *p; char *e, *abspath; int l, len; e = gfs_refreshdir(); if (e != NULL) return (e); e = lookup_path(path, -1, GFARM_INODE_LOOKUP, &n); if (e != NULL) { char *p_dir, *c_path; const char *base; struct gfarm_path_info info; /* * Before uncaching the metadata, check a typical case * such that the parent directory exists. */ if (gfs_realpath_canonical_parent(path, &p_dir) == NULL) { base = gfarm_path_dir_skip(path); c_path = malloc(strlen(p_dir) + 1 + strlen(base) + 1); if (c_path == NULL) { free(p_dir); return (GFARM_ERR_NO_MEMORY); } sprintf(c_path, "%s/%s", p_dir, base); free(p_dir); e = gfarm_i_path_info_get(c_path, &info); free(c_path); if (e != NULL) return (e); else gfarm_path_info_free(&info); } /* there may be inconsistency, refresh and lookup again. */ gfs_i_uncachedir(); if (gfs_refreshdir() == NULL) e = lookup_path(path, -1, GFARM_INODE_LOOKUP, &n); } if (e != NULL) return (e); len = 0; for (p = n; p != root; p = p->parent) { if (p != n) ++len; /* for '/' */ len += strlen(p->name); } abspath = malloc(len + 1); if (abspath == NULL) return (GFARM_ERR_NO_MEMORY); abspath[len] = '\0'; for (p = n; p != root; p = p->parent) { if (p != n) abspath[--len] = '/'; l = strlen(p->name); len -= l; memcpy(abspath + len, p->name, l); } *abspathp = abspath; return (NULL); }
char * gfarm_canonical_path_for_creation(const char *gfarm_file, char **canonic_pathp) { const char *basename; char *dir, *e, *dir_canonic; const char *lastc, *ini_lastc; *canonic_pathp = NULL; /* cause SEGV, if return value is ignored */ /* Expand '~'. */ if (gfarm_file[0] == '~') { char *expanded_gfarm_file; e = gfarm_path_expand_home(gfarm_file, &expanded_gfarm_file); if (e != NULL) return (e); assert(expanded_gfarm_file[0] != '~'); e = gfarm_canonical_path_for_creation( expanded_gfarm_file, canonic_pathp); free(expanded_gfarm_file); return (e); } /* '' or 'gfarm:' case */ if (gfarm_file[0] == '\0') { char cwd[PATH_MAX + 1]; e = gfs_getcwd(cwd, sizeof(cwd)); if (e != NULL) return (e); return (gfarm_canonical_path_for_creation(cwd, canonic_pathp)); } /* Eliminate unnecessary '/'s following the basename. */ lastc = ini_lastc = &gfarm_file[strlen(gfarm_file) - 1]; while (gfarm_file < lastc && *lastc == '/') --lastc; if (gfarm_file == lastc) { /* * In this case, given gfarm_file is '/' or contains * only several '/'s. This means to attempt to create * the root directory. Because the root directory * should exist, the attempt will fail with the error * of 'already exist'. However, this case such that * the canonical name is "" causes many problems. * That is why the error of 'already exist' is * returned here. */ return (GFARM_ERR_ALREADY_EXISTS); } else if (lastc != ini_lastc) { char *eliminated_gfarm_file; ++lastc; eliminated_gfarm_file = malloc(lastc - gfarm_file + 1); if (eliminated_gfarm_file == NULL) return (GFARM_ERR_NO_MEMORY); strncpy(eliminated_gfarm_file, gfarm_file, lastc - gfarm_file); eliminated_gfarm_file[lastc - gfarm_file] = '\0'; e = gfarm_canonical_path_for_creation( eliminated_gfarm_file, canonic_pathp); free(eliminated_gfarm_file); return (e); } basename = gfarm_path_dir_skip(gfarm_file); dir = NULL; if (basename == gfarm_file) { /* "filename" */ dir = strdup("."); if (dir == NULL) return (GFARM_ERR_NO_MEMORY); } else if (basename == gfarm_file + 1) { /* "/filename" */ dir = strdup("/"); if (dir == NULL) return (GFARM_ERR_NO_MEMORY); } else { /* /.../.../filename */ dir = malloc(basename - 2 - gfarm_file + 2); if (dir == NULL) return (GFARM_ERR_NO_MEMORY); strncpy(dir, gfarm_file, basename - 2 - gfarm_file + 1); dir[basename - 2 - gfarm_file + 1] = '\0'; } /* Check the existence of the parent directory. */ e = gfarm_canonical_path(dir, &dir_canonic); free(dir); if (e != NULL) return (e); *canonic_pathp = malloc(strlen(dir_canonic) + 1 + strlen(basename) + 1); if (*canonic_pathp == NULL) return (GFARM_ERR_NO_MEMORY); /* * When the 'dir_canonic' is a null string, *canonic_pathp * will start with '/' incorrectly. */ if (dir_canonic[0] == '\0') strcpy(*canonic_pathp, basename); else sprintf(*canonic_pathp, "%s/%s", dir_canonic, basename); free(dir_canonic); return (NULL); }
static int gfarm_register_file(char *gfarm_url, char *node_index, char *hostname, int total_nodes, char *filename, int auto_index) { struct stat s; struct gfs_stat gs; char *e, *target_url = NULL; int executable_file = 0; if (stat(filename, &s) == 0) { if (!S_ISREG(s.st_mode)) { fprintf(stderr, "%s: not a regular file", filename); return (-1); } if ((s.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) != 0) executable_file = 1; } else if (strcmp(filename, "-")) { perror(filename); return (-1); } e = gfs_stat(gfarm_url, &gs); if (e == NULL && GFARM_S_ISDIR(gs.st_mode)) { char *bname; /* gfarm_url is a directory */ gfs_stat_free(&gs); if (auto_index && total_nodes > 1 && !executable_file) { /* * In the auto index mode, the target Gfarm URL * should be a regular file when two or more local * non-executable files will be registered for * preventing unexpected results. */ fprintf(stderr, "%s: not a regular file. " "The target Gfarm URL should be a " "regular file when registering two or " "more local files.\n", gfarm_url); return (-1); } bname = basename(filename); target_url = malloc(strlen(gfarm_url) + strlen(bname) + 2); if (target_url == NULL) { fprintf(stderr, "not enough memory\n"); return (-1); } strcpy(target_url, gfarm_url); if (*gfarm_path_dir_skip(gfarm_url_prefix_skip(target_url)) != '\0') strcat(target_url, "/"); strcat(target_url, bname); } else if (e == NULL) gfs_stat_free(&gs); if (target_url == NULL) { target_url = strdup(gfarm_url); if (target_url == NULL) { fprintf(stderr, "not enough memory\n"); return (-1); } } if (executable_file) { /* register a binary executable. */ /* * In auto index case, node_index does not stand for * architecture. */ if (auto_index) node_index = NULL; if (node_index == NULL) { if (hostname == NULL) { char *self_name; e = gfarm_host_get_canonical_self_name( &self_name); if (e != NULL) { fprintf(stderr, "%s: %s\n", gfarm_host_get_self_name(), e); return (-1); } node_index = gfarm_host_info_get_architecture_by_host( self_name); } else { char *c_name; e = gfarm_host_get_canonical_name( hostname, &c_name); if (e != NULL) { fprintf(stderr, "%s: %s\n", hostname, e); return (-1); } node_index = gfarm_host_info_get_architecture_by_host( c_name); free(c_name); } } if (node_index == NULL) { fprintf(stderr, "%s: cannot determine the architecture " "of %s.\n", program_name, gfarm_host_get_self_name()); return (-1); } if (total_nodes <= 0) { if (gfs_pio_get_node_size(&total_nodes) != NULL) total_nodes = 1; } if (!opt_force) { struct gfs_stat s; if (gfs_stat_section(target_url, node_index, &s) == NULL) { gfs_stat_free(&s); e = "already exist"; goto finish; } } e = gfarm_url_fragment_register(target_url, node_index, GFARM_FILE_DONTCARE, hostname, filename); /* * XXX - gfarm_url_replicate() to replicate * 'total_nodes' copies of target_url. */ } else { char index_str[GFARM_INT32STRLEN + 1]; /* register a file fragment. */ if (node_index == NULL) { int index; e = gfs_pio_get_node_rank(&index); if (e != NULL) { fprintf(stderr, "%s: missing -I <Gfarm index>\n", program_name); return (-1); } sprintf(index_str, "%d", index); node_index = index_str; } if (total_nodes <= 0) { e = gfs_pio_get_node_size(&total_nodes); if (e != NULL) { fprintf(stderr, "%s: missing -N " "<total num of fragments>\n", program_name); return (-1); } } if (!opt_force) { struct gfs_stat s; if (gfs_stat_section(target_url, node_index, &s) == NULL) { gfs_stat_free(&s); e = "already exist"; goto finish; } } e = gfarm_url_fragment_register(target_url, node_index, total_nodes, hostname, filename); } finish: if (e != NULL) { fprintf(stderr, "%s: %s\n", target_url, e); return (-1); } free(target_url); return (0); }
char * list_dir(char *prefix, char *dirname, int *need_newline) { char *e, *s, *path, *e_save = NULL; gfarm_stringlist names; gfs_glob_t types; GFS_Dir dir; struct gfs_dirent *entry; int len = strlen(prefix) + strlen(dirname); path = malloc(len + 1 + 1); if (path == NULL) return (GFARM_ERR_NO_MEMORY); sprintf(path, "%s%s", prefix, dirname); e = gfarm_stringlist_init(&names); if (e != NULL) { fprintf(stderr, "%s: %s\n", program_name, e); free(path); return (e); } e = gfs_glob_init(&types); if (e != NULL) { fprintf(stderr, "%s: %s\n", program_name, e); gfarm_stringlist_free(&names); free(path); return (e); } e = gfs_opendir(path, &dir); if (e != NULL) { fprintf(stderr, "%s: %s\n", path, e); gfs_glob_free(&types); gfarm_stringlist_free(&names); free(path); return (e); } while ((e = gfs_readdir(dir, &entry)) == NULL && entry != NULL) { s = strdup(entry->d_name); if (s == NULL) { e = GFARM_ERR_NO_MEMORY; break; } gfarm_stringlist_add(&names, s); gfs_glob_add(&types, entry->d_type); } if (e != NULL) { fprintf(stderr, "%s%s: %s\n", prefix, dirname, e); e_save = e; } gfs_closedir(dir); if (*gfarm_path_dir_skip(gfarm_url_prefix_skip(path)) != '\0') { path[len] = '/'; path[len + 1] = '\0'; } e = list_files(path, gfarm_stringlist_length(&names), GFARM_STRINGLIST_STRARRAY(names), need_newline); if (e_save == NULL) e_save = e; if (option_recursive) { int i; for (i = 0; i < gfarm_stringlist_length(&names); i++) { s = GFARM_STRINGLIST_STRARRAY(names)[i]; if (s[0] == '.' && (s[1] == '\0' || (s[1] == '.' && s[2] == '\0'))) continue; if (gfs_glob_elem(&types, i) == GFS_DT_DIR) { e = list_dirs(path, 1, &s, need_newline); if (e_save == NULL) e_save = e; } } } gfs_glob_free(&types); gfarm_stringlist_free_deeply(&names); free(path); return (e_save); }