Exemple #1
0
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);
}
Exemple #2
0
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);
}
Exemple #3
0
/* 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, &sections);
	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);
}
Exemple #4
0
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);
}
Exemple #5
0
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);
}
Exemple #6
0
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;
}
Exemple #7
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);
}
Exemple #8
0
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);
}
Exemple #9
0
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";
}
Exemple #10
0
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);
}
Exemple #11
0
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);
}
Exemple #12
0
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, &sections);
	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,
					    &sections[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);
}
Exemple #13
0
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);
}
Exemple #14
0
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, &sections);
	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);
}
Exemple #15
0
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);
}
Exemple #16
0
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);
}
Exemple #17
0
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);
}
Exemple #18
0
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);
}
Exemple #19
0
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);
}
Exemple #20
0
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);
}
Exemple #21
0
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, &sections);
	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);
}
Exemple #22
0
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);
}
Exemple #23
0
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);
}
Exemple #24
0
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";
}
Exemple #25
0
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, &sections);
	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);
}
Exemple #26
0
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);
}
Exemple #27
0
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);
}
Exemple #28
0
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);
}
Exemple #29
0
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);
		}
	}
}
Exemple #30
0
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);
}