char * gfs_pio_open(const char *url, int flags, GFS_File *gfp) { char *e, *pathname; GFS_File gf; gfarm_timerval_t t1, t2; gfs_profile(gfarm_gettimerval(&t1)); if ((flags & GFARM_FILE_ACCMODE) != GFARM_FILE_RDONLY) { #if 0 /* XXX - ROOT I/O opens a new file with O_CREAT|O_RDRW mode. */ e = GFARM_ERR_OPERATION_NOT_SUPPORTED; /* XXX */ goto finish; #else flags |= GFARM_FILE_CREATE; #endif } e = gfarm_url_make_path(url, &pathname); if (e != NULL) goto finish; e = gfs_file_alloc(&gf); if (e != NULL) { free(pathname); goto finish; } gf->open_flags = flags; gf->mode |= GFS_FILE_MODE_READ; if (((flags & GFARM_FILE_ACCMODE) == GFARM_FILE_RDWR) || ((flags & GFARM_FILE_ACCMODE) == GFARM_FILE_WRONLY)) gf->mode |= GFS_FILE_MODE_WRITE; e = gfarm_path_info_get(pathname, &gf->pi); free(pathname); if (e != NULL) goto finish; e = gfarm_path_info_access(&gf->pi, GFS_R_OK); if (e != NULL) { gfarm_path_info_free(&gf->pi); gfs_file_free(gf); goto finish; } if (!GFARM_S_ISREG(gf->pi.status.st_mode)) { if (GFARM_S_ISDIR(gf->pi.status.st_mode)) e = GFARM_ERR_IS_A_DIRECTORY; else e = GFARM_ERR_OPERATION_NOT_SUPPORTED; gfarm_path_info_free(&gf->pi); gfs_file_free(gf); goto finish; } gf->mode |= GFS_FILE_MODE_NSEGMENTS_FIXED; *gfp = gf; e = NULL; finish: gfs_profile(gfarm_gettimerval(&t2)); gfs_profile(gfs_pio_open_time += gfarm_timerval_sub(&t2, &t1)); return (e); }
char * gfs_rmdir(const char *pathname) { char *canonic_path, *e, *e_tmp; struct gfarm_path_info pi; GFS_Dir dir; struct gfs_dirent *entry; e = gfarm_url_make_path_for_creation(pathname, &canonic_path); /* We permit missing gfarm: prefix here as a special case */ if (e == GFARM_ERR_GFARM_URL_PREFIX_IS_MISSING) e = gfarm_canonical_path_for_creation(pathname, &canonic_path); if (e != NULL) return (e); e = gfarm_path_info_get(canonic_path, &pi); if (e != NULL) goto error_free_canonic_path; if (!GFARM_S_ISDIR(pi.status.st_mode)) { gfarm_path_info_free(&pi); e = GFARM_ERR_NOT_A_DIRECTORY; goto error_free_canonic_path; } gfarm_path_info_free(&pi); e = gfs_opendir(pathname, &dir); if (e == NULL) { while ((e = gfs_readdir(dir, &entry)) == NULL) { if (entry == NULL) { /* OK, remove the directory */ e = gfarm_path_info_remove(canonic_path); break; } if ((entry->d_namlen == 1 && entry->d_name[0] == '.') || (entry->d_namlen == 2 && entry->d_name[0] == '.' && entry->d_name[1] == '.')) continue; /* "." or ".." */ /* Not OK */ e = GFARM_ERR_DIRECTORY_NOT_EMPTY; break; } e_tmp = gfs_closedir(dir); if (e == NULL) e = e_tmp; } error_free_canonic_path: free(canonic_path); return (e); }
/* Create a set of architectures that the program is registered for */ static char * program_arch_set(char *program, struct gfarm_hash_table **arch_setp) { char *e, *gfarm_file; struct gfarm_path_info pi; struct gfarm_file_section_info *sections; struct gfarm_hash_table *arch_set; int i, nsections, created; e = gfarm_url_make_path(program, &gfarm_file); if (e != NULL) return (e); e = gfarm_path_info_get(gfarm_file, &pi); if (e != NULL) { if (e == GFARM_ERR_NO_SUCH_OBJECT) e = "such program isn't registered"; free(gfarm_file); return (e); } if (!GFARM_S_IS_PROGRAM(pi.status.st_mode)) { gfarm_path_info_free(&pi); free(gfarm_file); return ("specified command is not an executable"); } e = gfarm_file_section_info_get_all_by_file(gfarm_file, &nsections, §ions); gfarm_path_info_free(&pi); free(gfarm_file); if (e != NULL) return ("no binary is registered as the specified command"); arch_set = gfarm_hash_table_alloc(ARCH_SET_HASHTAB_SIZE, gfarm_hash_default, gfarm_hash_key_equal_default); if (arch_set == NULL) { gfarm_file_section_info_free_all(nsections, sections); return (GFARM_ERR_NO_MEMORY); } /* register architectures of the program to `arch_set' */ for (i = 0; i < nsections; i++) { if (gfarm_hash_enter(arch_set, sections[i].section, strlen(sections[i].section) + 1, sizeof(int), &created) == NULL) { free_arch_set(arch_set); gfarm_file_section_info_free_all(nsections, sections); return (GFARM_ERR_NO_MEMORY); } } gfarm_file_section_info_free_all(nsections, sections); *arch_setp = arch_set; return (NULL); }
char * gfarm_cache_path_info_get(const char *pathname, struct gfarm_path_info *info) { char *e; e = cache_path_info_get(pathname, info); #if 0 /* for debug */ if (e == NULL) { struct gfarm_path_info tmp; char *e2; e2 = gfarm_metadb_path_info_get(pathname, &tmp); if (e2 == NULL) { if (compare_path_info_except_time(info, &tmp) != 0) { _debug("! different cache\n"); } gfarm_path_info_free(&tmp); } } #endif if (e != NULL && e != GFARM_ERR_NO_SUCH_OBJECT) { e = gfarm_metadb_path_info_get(pathname, info); if (e == GFARM_ERR_NO_SUCH_OBJECT) cache_path_info_put(pathname, NULL); /* cache NOENT */ else if (e == NULL) cache_path_info_put(pathname, info); } return (e); }
char * gfs_pio_close(GFS_File gf) { char *e, *e_save; gfarm_timerval_t t1, t2; gfs_profile(gfarm_gettimerval(&t1)); e_save = gfs_pio_check_view_default(gf); if (e_save == NULL) { if ((gf->mode & GFS_FILE_MODE_WRITE) != 0) e_save = gfs_pio_flush(gf); e = (*gf->ops->view_close)(gf); if (e_save == NULL) e_save = e; } gfarm_path_info_free(&gf->pi); free(gf->buffer); free(gf); gfs_profile(gfarm_gettimerval(&t2)); gfs_profile(gfs_pio_close_time += gfarm_timerval_sub(&t2, &t1)); return (e_save); }
static void cache_path_info_free() { struct gfarm_hash_iterator iterator; struct gfarm_hash_entry *he; struct path_info_cache *pic; #ifdef DEBUG char *key; char path[PATH_MAX]; #endif gfarm_hash_iterator_begin(cache_table, &iterator); while (1) { he = gfarm_hash_iterator_access(&iterator); if (he == NULL) break; pic = gfarm_hash_entry_data(he); #ifdef DEBUG key = gfarm_hash_entry_key(he); memset(path, 0, PATH_MAX); memcpy(path, key, gfarm_hash_entry_key_length(he)); _debug("! free path_info cache: %d: %s\n", pic->noent, path); #endif if (pic->noent == CACHE_SET) gfarm_path_info_free(&pic->info); gfarm_hash_iterator_next(&iterator); } /* ?? gfarm_hash_iterator_purge(&iterator); */ gfarm_hash_table_free(cache_table); prepare_cache_table = 0; }
static int get_nsections(char *gfarm_url, int *nsectionsp) { char *e, *gfarm_file; struct gfarm_path_info pi; e = gfarm_url_make_path(gfarm_url, &gfarm_file); if (e != NULL) { fprintf(stderr, "%s: gfarm_url_make_path(%s): %s\n", program_name, gfarm_url, e); error_happened = 1; return (0); } e = gfarm_path_info_get(gfarm_file, &pi); free(gfarm_file); if (e != NULL) { if (e == GFARM_ERR_NO_SUCH_OBJECT) fprintf(stderr, "%s: missing -N <total number of fragments>\n", program_name); else fprintf(stderr, "%s: gfarm_get_path_info(%s): %s\n", program_name, gfarm_url, e); error_happened = 1; return (0); } *nsectionsp = pi.status.st_nsections; gfarm_path_info_free(&pi); return (1); }
char * gfs_utimes(const char *gfarm_url, const struct gfarm_timespec *tsp) { char *e, *gfarm_file; struct gfarm_path_info pi; struct timeval now; e = gfarm_url_make_path(gfarm_url, &gfarm_file); if (e != NULL) return (e); e = gfarm_path_info_get(gfarm_file, &pi); free(gfarm_file); if (e != NULL) return (e); e = gfarm_path_info_access(&pi, GFS_W_OK); if (e != NULL) return (e); gettimeofday(&now, NULL); if (tsp == NULL) { pi.status.st_atimespec.tv_sec = pi.status.st_mtimespec.tv_sec = now.tv_sec; pi.status.st_atimespec.tv_nsec = pi.status.st_mtimespec.tv_nsec = now.tv_usec * 1000; } else { pi.status.st_atimespec = tsp[0]; pi.status.st_mtimespec = tsp[1]; } pi.status.st_ctimespec.tv_sec = now.tv_sec; pi.status.st_ctimespec.tv_nsec = now.tv_usec * 1000; e = gfarm_path_info_replace(pi.pathname, &pi); gfarm_path_info_free(&pi); return (e); }
static char * cache_path_info_remove(const char *pathname) { struct gfarm_hash_entry *he; int pathlen; struct path_info_cache *pic; if (!cache_path_info_init()) return (GFARM_PATH_INFO_CACHE_CANCEL); pathlen = strlen(pathname); he = gfarm_hash_lookup(cache_table, pathname, pathlen); if (he != NULL) { pic = gfarm_hash_entry_data(he); if (pic != NULL) { if (pic->noent == CACHE_SET) gfarm_path_info_free(&pic->info); if (gfarm_hash_purge(cache_table, pathname, pathlen)) { _debug("! remove path_info cache: %s\n", pathname); current_cache_num--; return (NULL); } } } return "cache_path_info_remove: no path_info cache"; }
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); }
char * gfs_pio_close(GFS_File gf) { char *e, *e_save; gfarm_timerval_t t1, t2; gfs_profile(gfarm_gettimerval(&t1)); e_save = gfs_pio_check_view_default(gf); if (e_save == NULL) { if ((gf->mode & GFS_FILE_MODE_WRITE) != 0) e_save = gfs_pio_flush(gf); e = (*gf->ops->view_close)(gf); if (e_save == NULL) e_save = e; } /* * When there is inconsistency, do not update/overwrite the * metadata. This inconsistency may come from the update by * other process or oneself such as 'nvi'. */ if (e_save == NULL) e_save = gfs_pio_update_times(gf); gfarm_path_info_free(&gf->pi); gfs_file_free(gf); gfs_profile(gfarm_gettimerval(&t2)); gfs_profile(gfs_pio_close_time += gfarm_timerval_sub(&t2, &t1)); return (e_save); }
static gfarm_error_t gfs_pio_view_global_ftruncate(GFS_File gf, gfarm_off_t length) { struct gfs_file_global_context *gc = gf->view_context; gfarm_error_t e; int i, fragment, nsections; gfarm_off_t section_length; struct gfarm_file_section_info *sections; char section_string[GFARM_INT32STRLEN + 1]; if (length < 0) return (GFARM_ERR_INVALID_ARGUMENT); if (length >= gc->offsets[gf->pi.status.st_nsections - 1]) fragment = gf->pi.status.st_nsections - 1; else fragment = gfs_pio_view_global_bsearch( length, gc->offsets, gf->pi.status.st_nsections - 1); section_length = length - gc->offsets[fragment]; e = gfs_pio_view_global_move_to(gf, fragment); if (e != GFARM_ERR_NO_ERROR) return (e); e = gfs_pio_truncate(gc->fragment_gf, section_length); if (e != GFARM_ERR_NO_ERROR) return (e); /* * Before updating path_info, try to update most recent information, * because the file mode may be updated by e.g. gfs_chmod(). */ if (gfarm_path_info_get(gf->pi.pathname, &pi) == NULL) { gfarm_path_info_free(&gf->pi); gf->pi = pi; } #if 0 /* We don't store file size in gfarm_path_info, this is just ignored */ gf->pi.status.st_size = length; #endif gf->pi.status.st_nsections = fragment + 1; e = gfarm_path_info_replace(gf->pi.pathname, &gf->pi); if (e != GFARM_ERR_NO_ERROR) return (e); e = gfarm_file_section_info_get_sorted_all_serial_by_file( gf->pi.pathname, &nsections, §ions); if (e != GFARM_ERR_NO_ERROR) return (e); sections[fragment].filesize = section_length; sprintf(section_string, "%d", fragment); e = gfarm_file_section_info_replace(gf->pi.pathname, section_string, §ions[fragment]); for (i = fragment + 1; i < nsections; i++) (void)gfs_unlink_section_internal(gf->pi.pathname, sections[i].section); gfarm_file_section_info_free_all(nsections, sections); return (e); }
char * gfarm_url_section_replicate_from_to(char *gfarm_url, char *section, char *srchost, char *dsthost) { char *e, *gfarm_file, *canonical_hostname, *if_hostname; struct sockaddr peer_addr; struct gfarm_path_info pi; struct gfarm_file_section_info si; gfarm_mode_t mode_allowed = 0; e = gfarm_url_make_path(gfarm_url, &gfarm_file); if (e != NULL) goto finish; e = gfarm_path_info_get(gfarm_file, &pi); if (e != NULL) goto finish_gfarm_file; e = gfarm_file_section_info_get(gfarm_file, section, &si); if (e != NULL) goto finish_path_info; e = gfarm_host_get_canonical_name(srchost, &canonical_hostname); if (e != NULL) goto finish_canonical_hostname; /* reflect "address_use" directive in the `srchost' */ e = gfarm_host_address_get(srchost, gfarm_spool_server_port, &peer_addr, &if_hostname); if (e != NULL) goto finish_section_info; /* * XXX - if the owner of a file is not the same, permit a * group/other write access - This should be fixed in the next * major release. */ if (strcmp(pi.status.st_user, gfarm_get_global_username()) != 0) { e = gfarm_path_info_access(&pi, GFS_R_OK); if (e != NULL) goto finish_path_info; mode_allowed = 022; } e = gfarm_file_section_replicate_from_to_internal( gfarm_file, section, (pi.status.st_mode | mode_allowed) & GFARM_S_ALLPERM, si.filesize, canonical_hostname, if_hostname, dsthost); free(if_hostname); finish_canonical_hostname: free(canonical_hostname); finish_section_info: gfarm_file_section_info_free(&si); finish_path_info: gfarm_path_info_free(&pi); finish_gfarm_file: free(gfarm_file); finish: return (e); }
char * gfs_stat_canonical_path(char *gfarm_file, struct gfs_stat *s) { char *e; int i, nsections; struct gfarm_file_section_info *sections; struct gfarm_path_info pi; long ino; e = gfs_get_ino(gfarm_file, &ino); if (e != NULL) return (e); e = gfarm_path_info_get(gfarm_file, &pi); if (e != NULL) return (e); *s = pi.status; s->st_ino = ino; s->st_user = strdup(s->st_user); s->st_group = strdup(s->st_group); gfarm_path_info_free(&pi); if (s->st_user == NULL || s->st_group == NULL) { gfs_stat_free(s); return (GFARM_ERR_NO_MEMORY); } if (!GFARM_S_ISREG(s->st_mode)) return (NULL); /* regular file */ e = gfarm_file_section_info_get_all_by_file(gfarm_file, &nsections, §ions); if (e != NULL) { gfs_stat_free(s); /* * If GFARM_ERR_NO_SUCH_OBJECT is returned here, * gfs_stat() incorrectly assumes that this is a directory, * and reports GFARM_ERR_NOT_A_DIRECTORY. */ return (GFARM_ERR_NO_FRAGMENT_INFORMATION); } s->st_size = 0; for (i = 0; i < nsections; i++) s->st_size += sections[i].filesize; s->st_nsections = nsections; gfarm_file_section_info_free_all(nsections, sections); return (NULL); }
static char * check_path_info(char *gfarm_file) { struct gfarm_path_info p_info; char *e; /* check whether the path info is already registered. */ e = gfarm_path_info_get(gfarm_file, &p_info); if (e != NULL) return (e); gfarm_path_info_free(&p_info); return (NULL); }
char * gfs_pio_open(const char *url, int flags, GFS_File *gfp) { char *e, *pathname; GFS_File gf; gfarm_timerval_t t1, t2; gfs_profile(gfarm_gettimerval(&t1)); if (flags & GFARM_FILE_CREATE) { e = GFARM_ERR_OPERATION_NOT_SUPPORTED; goto finish; } e = gfarm_url_make_path(url, &pathname); if (e != NULL) goto finish; e = gfs_file_alloc(&gf); if (e != NULL) { free(pathname); goto finish; } /* GFARM_FILE_EXCLUSIVE is a NOP with gfs_pio_open(). */ flags &= ~GFARM_FILE_EXCLUSIVE; gfs_pio_open_initialize_mode_flags(gf, flags); e = gfarm_path_info_get(pathname, &gf->pi); free(pathname); if (e != NULL) goto free_gf; e = gfs_pio_open_check_perm(gf); if (e != NULL) goto free_gf_pi; if ((flags & GFARM_FILE_TRUNC) == 0) gf->mode |= GFS_FILE_MODE_NSEGMENTS_FIXED; *gfp = gf; e = NULL; goto finish; free_gf_pi: gfarm_path_info_free(&gf->pi); free_gf: gfs_file_free(gf); finish: gfs_profile(gfarm_gettimerval(&t2)); gfs_profile(gfs_pio_open_time += gfarm_timerval_sub(&t2, &t1)); return (e); }
char * gfs_mkdir(const char *pathname, gfarm_mode_t mode) { char *user, *canonic_path, *e; struct gfarm_path_info pi; struct timeval now; mode_t mask; user = gfarm_get_global_username(); if (user == NULL) return ("unknown user"); e = gfarm_url_make_path_for_creation(pathname, &canonic_path); /* We permit missing gfarm: prefix here as a special case */ if (e == GFARM_ERR_GFARM_URL_PREFIX_IS_MISSING) e = gfarm_canonical_path_for_creation(pathname, &canonic_path); if (e != NULL) return (e); if (gfarm_path_info_get(canonic_path, &pi) == NULL) { gfarm_path_info_free(&pi); free(canonic_path); return (GFARM_ERR_ALREADY_EXISTS); } mask = umask(0); umask(mask); mode &= ~mask; gettimeofday(&now, NULL); pi.pathname = canonic_path; pi.status.st_mode = (GFARM_S_IFDIR | mode); pi.status.st_user = user; pi.status.st_group = "*"; /* XXX for now */ pi.status.st_atimespec.tv_sec = pi.status.st_mtimespec.tv_sec = pi.status.st_ctimespec.tv_sec = now.tv_sec; pi.status.st_atimespec.tv_nsec = pi.status.st_mtimespec.tv_nsec = pi.status.st_ctimespec.tv_nsec = now.tv_usec * GFARM_MILLISEC_BY_MICROSEC; pi.status.st_size = 0; pi.status.st_nsections = 0; e = gfarm_path_info_set(canonic_path, &pi); free(canonic_path); return (e); }
static char * cache_path_info_put(const char *pathname, struct gfarm_path_info *info) { struct gfarm_hash_entry *he; int pathlen; int created; struct path_info_cache *pic; if (!cache_path_info_init()) return (GFARM_PATH_INFO_CACHE_CANCEL); if (current_cache_num >= hash_size) cache_path_info_free(); /* clear all cache */ pathlen = strlen(pathname); /* set cache */ he = gfarm_hash_enter(cache_table, pathname, pathlen, sizeof(struct path_info_cache), &created); if (he == NULL) { _debug("! cache_path_info_put: no memory\n"); return (GFARM_ERR_NO_MEMORY); } pic = gfarm_hash_entry_data(he); _debug("! put path_info cache: %s\n", pathname); if (created) /* new cache */ current_cache_num++; else if (pic->noent == CACHE_SET) /* have path_info */ gfarm_path_info_free(&pic->info); if (info == NULL) { /* set NOENT */ pic->noent = CACHE_NOENT; _debug("! -> set NOENT: %s\n", pathname); } else { #ifdef DEBUG if (pic->noent == CACHE_NOENT) { _debug("! -> update cache from NOENT: %s\n", pathname); } #endif (void)gfarm_path_info_dup(info, &pic->info); pic->noent = CACHE_SET; } /* current time */ gettimeofday(&pic->time, NULL); return (NULL); }
char * gfarm_cache_size_set(const char *pathname, file_offset_t size) { char *e; struct gfarm_path_info info; e = cache_path_info_get(pathname, &info); if (e == NULL) { if (info.status.st_size != size) { _debug("! cache size: %s\n", pathname); info.status.st_size = size; e = cache_path_info_put(pathname, &info); } gfarm_path_info_free(&info); } return (e); }
char * gfs_stat_section(const char *gfarm_url, const char *section, struct gfs_stat *s) { char *e, *gfarm_file; struct gfarm_file_section_info sinfo; struct gfarm_path_info pi; long ino; e = gfarm_url_make_path(gfarm_url, &gfarm_file); if (e != NULL) return (e); e = gfs_get_ino(gfarm_file, &ino); if (e != NULL) { free(gfarm_file); return (e); } e = gfarm_path_info_get(gfarm_file, &pi); if (e != NULL) { free(gfarm_file); return (e); } *s = pi.status; s->st_ino = ino; s->st_user = strdup(s->st_user); s->st_group = strdup(s->st_group); gfarm_path_info_free(&pi); if (!GFARM_S_ISREG(s->st_mode)) { free(gfarm_file); return (NULL); } e = gfarm_file_section_info_get(gfarm_file, section, &sinfo); free(gfarm_file); if (e != NULL) return (e); s->st_size = sinfo.filesize; s->st_nsections = 1; gfarm_file_section_info_free(&sinfo); return (NULL); }
char * gfs_access(const char *gfarm_url, int mode) { char *e, *gfarm_file; struct gfarm_path_info pi; gfarm_mode_t stat_mode; int stat_nsections, nsections; struct gfarm_file_section_info *sections; e = gfarm_url_make_path(gfarm_url, &gfarm_file); if (e != NULL) return (e); e = gfarm_path_info_get(gfarm_file, &pi); if (e != NULL) { free(gfarm_file); return (e); } stat_mode = pi.status.st_mode; stat_nsections = pi.status.st_nsections; e = gfarm_path_info_access(&pi, mode); gfarm_path_info_free(&pi); if (e != NULL) { free(gfarm_file); return (e); } if (GFARM_S_ISDIR(stat_mode)) { free(gfarm_file); return (NULL); } /* * Check all fragments are ready or not. * XXX - is this check necessary? */ e = gfarm_file_section_info_get_all_by_file( gfarm_file, &nsections, §ions); free(gfarm_file); if (e != NULL) return (e); gfarm_file_section_info_free_all(nsections, sections); if (!GFARM_S_IS_PROGRAM(stat_mode) && nsections != stat_nsections) e = GFARM_ERR_FRAGMENT_NUMBER_DOES_NOT_MATCH; return (e); }
char * gfarm_url_fragment_number(char *gfarm_url, int *np) { char *e, *gfarm_file; struct gfarm_path_info pi; e = gfarm_url_make_path(gfarm_url, &gfarm_file); if (e != NULL) return (e); e = gfarm_path_info_get(gfarm_file, &pi); free(gfarm_file); if (e != NULL) return (e); if (!GFARM_S_IS_FRAGMENTED_FILE(pi.status.st_mode)) return (GFARM_ERR_OPERATION_NOT_PERMITTED); *np = pi.status.st_nsections; gfarm_path_info_free(&pi); return (NULL); }
char * gfarm_url_section_replicate_to(char *gfarm_url, char *section, char *dsthost) { char *e, *gfarm_file; struct gfarm_path_info pi; struct gfarm_file_section_info si; gfarm_mode_t mode_allowed = 0; e = gfarm_url_make_path(gfarm_url, &gfarm_file); if (e != NULL) goto finish; e = gfarm_path_info_get(gfarm_file, &pi); if (e != NULL) goto finish_gfarm_file; e = gfarm_file_section_info_get(gfarm_file, section, &si); if (e != NULL) goto finish_path_info; /* * XXX - if the owner of a file is not the same, permit a * group/other write access - This should be fixed in the next * major release. */ if (strcmp(pi.status.st_user, gfarm_get_global_username()) != 0) { e = gfarm_path_info_access(&pi, GFS_R_OK); if (e != NULL) goto finish_path_info; mode_allowed = 022; } e = gfarm_file_section_replicate_to_internal( gfarm_file, section, (pi.status.st_mode | mode_allowed) & GFARM_S_ALLPERM, si.filesize, dsthost); gfarm_file_section_info_free(&si); finish_path_info: gfarm_path_info_free(&pi); finish_gfarm_file: free(gfarm_file); finish: return (e); }
static char * cache_path_info_get(const char *pathname, struct gfarm_path_info *info) { struct gfarm_hash_entry *he; int pathlen; struct path_info_cache *pic; struct timeval now; if (!cache_path_info_init()) return (GFARM_PATH_INFO_CACHE_CANCEL); pathlen = strlen(pathname); he = gfarm_hash_lookup(cache_table, pathname, pathlen); if (he != NULL) { pic = gfarm_hash_entry_data(he); if (pic != NULL) { /* check term of validity */ gettimeofday(&now, NULL); gfarm_timeval_sub(&now, &pic->time); if (gfarm_timeval_cmp(&now, &cache_timeout) >= 0) { _debug("! expire path_info cache: %s\n", pathname); #if 1 /* purge */ if (pic->noent == CACHE_SET) gfarm_path_info_free(&pic->info); if (gfarm_hash_purge(cache_table, pathname, strlen(pathname))) current_cache_num--; #endif return "expired path_info cache content"; } _debug("! use path_info cache: %s\n", pathname); if (pic->noent == CACHE_NOENT) /* NOENT cache */ return (GFARM_ERR_NO_SUCH_OBJECT); return gfarm_path_info_dup(&pic->info, info); } } return "cache_path_info_get: no path_info cache"; }
char * gfs_access(char *gfarm_url, int mode) { char *e, *gfarm_file; struct gfarm_path_info pi; int nsections; struct gfarm_file_section_info *sections; e = gfarm_url_make_path(gfarm_url, &gfarm_file); if (e != NULL) return (e); e = gfarm_path_info_get(gfarm_file, &pi); if (e != NULL) { free(gfarm_file); return (e); } /* * Check whether the gfarm_url can be accessible by other * processes or not. * * XXX - temporal solution until file locking will be implemented. */ e = gfarm_file_section_info_get_all_by_file(gfarm_file, &nsections, §ions); free(gfarm_file); if (e != NULL) { return (e); } gfarm_file_section_info_free_all(nsections, sections); if (!GFARM_S_IS_PROGRAM(pi.status.st_mode) && nsections != pi.status.st_nsections) return (GFARM_ERR_FRAGMENT_NUMBER_DOES_NOT_MATCH); e = gfarm_path_info_access(&pi, mode); gfarm_path_info_free(&pi); return (e); }
char * gfs_pio_create(const char *url, int flags, gfarm_mode_t mode, GFS_File *gfp) { char *e, *pathname; GFS_File gf; int pi_available = 0; mode_t mask; char *user; gfarm_timerval_t t1, t2; gfs_profile(gfarm_gettimerval(&t1)); user = gfarm_get_global_username(); if (user == NULL) { e = "gfarm_pio_create(): programming error, " "gfarm library isn't properly initialized"; goto finish; } #if 0 /* XXX - ROOT I/O opens a new file with O_CREAT|O_RDRW mode. */ if ((flags & GFARM_FILE_ACCMODE) != GFARM_FILE_WRONLY) { e = GFARM_ERR_OPERATION_NOT_SUPPORTED; /* XXX */ goto finish; } #endif mask = umask(0); umask(mask); mode &= ~mask; e = gfarm_url_make_path_for_creation(url, &pathname); if (e != NULL) goto finish; e = gfs_file_alloc(&gf); if (e != NULL) { free(pathname); goto finish; } /* gfs_pio_create() always assumes CREATE, TRUNC */ flags |= GFARM_FILE_CREATE | GFARM_FILE_TRUNC; if ((flags & (GFARM_FILE_TRUNC|GFARM_FILE_SEQUENTIAL)) != (GFARM_FILE_TRUNC|GFARM_FILE_SEQUENTIAL)) { /* MODE_READ is needed to re-calculate checksum. */ flags = (flags & ~GFARM_FILE_ACCMODE) | GFARM_FILE_RDWR; } else if ((flags & ~GFARM_FILE_ACCMODE) == GFARM_FILE_RDONLY) { flags = (flags & ~GFARM_FILE_ACCMODE) | GFARM_FILE_WRONLY; } gf->open_flags = flags; gf->mode = GFS_FILE_MODE_WRITE; if ((flags & GFARM_FILE_ACCMODE) == GFARM_FILE_RDWR) gf->mode |= GFS_FILE_MODE_READ; e = gfarm_path_info_get(pathname, &gf->pi); if (e != NULL && e != GFARM_ERR_NO_SUCH_OBJECT) { free(pathname); gfs_file_free(gf); goto finish; } if (e == NULL) { /* XXX unlink and re-create the file? */ free(pathname); e = gfarm_path_info_access(&gf->pi, GFS_W_OK); if (e != NULL) { gfarm_path_info_free(&gf->pi); gfs_file_free(gf); goto finish; } if (!GFARM_S_ISREG(gf->pi.status.st_mode)) { if (GFARM_S_ISDIR(gf->pi.status.st_mode)) e = GFARM_ERR_IS_A_DIRECTORY; else e = GFARM_ERR_OPERATION_NOT_SUPPORTED; gfarm_path_info_free(&gf->pi); gfs_file_free(gf); goto finish; } /* * XXX should check the follows: * - the mode is consistent among same job * - creator of the metainfo has same job id * - O_TRUNC / !O_TRUNC case */ mode |= GFARM_S_IFREG; if (GFARM_S_IS_PROGRAM(mode) != GFS_FILE_IS_PROGRAM(gf)) { gfarm_path_info_free(&gf->pi); gfs_file_free(gf); e = GFARM_ERR_OPERATION_NOT_PERMITTED; goto finish; } pi_available = 1; } if (!pi_available) { struct timeval now; gettimeofday(&now, NULL); gf->pi.pathname = pathname; gf->pi.status.st_mode = (GFARM_S_IFREG | mode); gf->pi.status.st_user = strdup(user); /* XXX NULL check */ gf->pi.status.st_group = strdup("*"); /* XXX for now */ gf->pi.status.st_atimespec.tv_sec = gf->pi.status.st_mtimespec.tv_sec = gf->pi.status.st_ctimespec.tv_sec = now.tv_sec; gf->pi.status.st_atimespec.tv_nsec = gf->pi.status.st_mtimespec.tv_nsec = gf->pi.status.st_ctimespec.tv_nsec = now.tv_usec * 1000; gf->pi.status.st_size = 0; gf->pi.status.st_nsections = 0; } *gfp = gf; gfs_uncachedir(); e = NULL; finish: gfs_profile(gfarm_gettimerval(&t2)); gfs_profile(gfs_pio_create_time += gfarm_timerval_sub(&t2, &t1)); return (e); }
char * gfs_pio_set_view_section(GFS_File gf, const char *section, char *if_hostname, int flags) { struct gfs_file_section_context *vc; char *e; int is_local_host; gfarm_timerval_t t1, t2; gfs_profile(gfarm_gettimerval(&t1)); e = gfs_pio_set_view_default(gf); if (e != NULL) goto profile_finish; vc = malloc(sizeof(struct gfs_file_section_context)); if (vc == NULL) { e = gf->error = GFARM_ERR_NO_MEMORY; goto profile_finish; } vc->section = strdup(section); if (vc->section == NULL) { free(vc); e = gf->error = GFARM_ERR_NO_MEMORY; goto profile_finish; } retry: if (if_hostname != NULL) { e = gfarm_host_get_canonical_name(if_hostname, &vc->canonical_hostname); if (e == GFARM_ERR_UNKNOWN_HOST) { /* FT - invalid hostname, delete section copy info */ if (gfarm_file_section_copy_info_remove( gf->pi.pathname, vc->section, if_hostname) == NULL) e = GFARM_ERR_INCONSISTENT_RECOVERABLE; if (e == GFARM_ERR_INCONSISTENT_RECOVERABLE && (flags & GFARM_FILE_NOT_RETRY) == 0 && (gf->open_flags & GFARM_FILE_NOT_RETRY) == 0) { if_hostname = NULL; goto retry; } goto finish; } else if (e != NULL) goto finish; } else if ((gf->open_flags & GFARM_FILE_CREATE) != 0) { e = gfarm_host_get_canonical_self_name(&if_hostname); if (e == NULL) e = gfarm_schedule_search_idle_hosts( 1, &if_hostname, 1, &vc->canonical_hostname); if (e == NULL) e = gfarm_fixedstrings_dup( 1, &vc->canonical_hostname, &vc->canonical_hostname); if (e != NULL) { /* * local host is not a file system node, or * 'gfsd' on a local host is not running. */ e = gfarm_schedule_search_idle_by_all(1, &if_hostname); if (e != NULL) goto finish; vc->canonical_hostname = if_hostname; } } else { e = gfarm_file_section_host_schedule_with_priority_to_local( gf->pi.pathname, vc->section, &if_hostname); if (e != NULL) goto finish; vc->canonical_hostname = if_hostname; /* must be already canonical */ } is_local_host = gfarm_canonical_hostname_is_local( vc->canonical_hostname); if ((gf->open_flags & GFARM_FILE_CREATE) != 0) { struct gfarm_path_info pi; e = gfarm_path_info_set(gf->pi.pathname, &gf->pi); if (e == GFARM_ERR_ALREADY_EXISTS && (e = gfarm_path_info_get(gf->pi.pathname, &pi)) == NULL) { if (GFS_FILE_IS_PROGRAM(gf) != GFARM_S_IS_PROGRAM(pi.status.st_mode)) e = GFARM_ERR_OPERATION_NOT_PERMITTED; if (e == NULL && !GFS_FILE_IS_PROGRAM(gf)) { if (gf->pi.status.st_nsections != pi.status.st_nsections) { e = GFARM_ERR_FRAGMENT_NUMBER_DOES_NOT_MATCH; } else { #if 0 assert(gf->pi.status.st_mode & GFS_FILE_MODE_NSEGMENTS_FIXED); #endif } } if (e != NULL) { gfarm_path_info_free(&pi); } else { gfarm_path_info_free(&gf->pi); gf->pi = pi; } /* * XXX should check the follows: * - creator of the metainfo has same job id * - mode is consistent among same job * - nfragments is consistent among same job */ } if (e != NULL) goto free_host; } /* delete the file section when opening with a truncation flag. */ if ((gf->open_flags & GFARM_FILE_TRUNC) != 0) (void)gfs_unlink_section(gf->pi.pathname, vc->section); gf->ops = &gfs_pio_view_section_ops; gf->view_context = vc; gf->view_flags = flags; gf->p = gf->length = 0; gf->io_offset = gf->offset = 0; gf->mode |= GFS_FILE_MODE_CALC_DIGEST; EVP_DigestInit(&vc->md_ctx, GFS_DEFAULT_DIGEST_MODE); if (!is_local_host && ((((gf->open_flags & GFARM_FILE_REPLICATE) != 0 || gf_on_demand_replication ) && (flags & GFARM_FILE_NOT_REPLICATE) == 0) || (flags & GFARM_FILE_REPLICATE) != 0)) { e = replicate_section_to_local(gf, vc->section, if_hostname); /* FT - inconsistent metadata has been fixed. try again. */ if (e == GFARM_ERR_INCONSISTENT_RECOVERABLE && (flags & GFARM_FILE_NOT_RETRY) == 0 && (gf->open_flags & GFARM_FILE_NOT_RETRY) == 0) { if_hostname = NULL; free(vc->canonical_hostname); goto retry; } if (e != NULL) goto free_host; free(vc->canonical_hostname); e = gfarm_host_get_canonical_self_name( &vc->canonical_hostname); if (e != NULL) goto finish; vc->canonical_hostname = strdup(vc->canonical_hostname); if (vc->canonical_hostname == NULL) { e = GFARM_ERR_NO_MEMORY; goto finish; } is_local_host = 1; } if (is_local_host) e = gfs_pio_open_local_section(gf, flags); else e = gfs_pio_open_remote_section(gf, if_hostname, flags); /* FT - inconsistent metadata has been fixed. try again. */ if (e == GFARM_ERR_INCONSISTENT_RECOVERABLE && (flags & GFARM_FILE_NOT_RETRY) == 0 && (gf->open_flags & GFARM_FILE_NOT_RETRY) == 0) { if_hostname = NULL; free(vc->canonical_hostname); goto retry; } free_host: if (e != NULL) free(vc->canonical_hostname); finish: if (e != NULL) { free(vc->section); free(vc); gf->view_context = NULL; gfs_pio_set_view_default(gf); } gf->error = e; profile_finish: gfs_profile(gfarm_gettimerval(&t2)); gfs_profile(gfs_pio_set_view_section_time += gfarm_timerval_sub(&t2, &t1)); 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); }