From: <n-...@us...> - 2009-03-12 20:57:26
|
Revision: 4085 http://gfarm.svn.sourceforge.net/gfarm/?rev=4085&view=rev Author: n-soda Date: 2009-03-12 20:57:02 +0000 (Thu, 12 Mar 2009) Log Message: ----------- - implement gfs_symlink() and gfs_readlink() to support symbolic links in gfarm2fs, although pathname lookup routine in libgfarm side still doesn't really follow symbolic links. Note that symbolic link handling in libgfarm cannot be compatible with the handling in gfarm2fs, because those use different mount points (libgfarm doesn't know the mount point that users of gfarm2fs use). So, this implementation is practically good enough as far as people are using gfarm2fs. - add `gfln' command to create hard links and symbolic links. - make `gfls -l' cope with symbolic links. - make `gfls -l' display number of hard links. - add gfs_lstat() and gfs_lstat_cached() function. currently gfs_stat() (and gfs_stat_cached()) work as gfs_lstat() (and gfs_lstat_cached()). XXX Gfarm APIs should follow symbolic links. Modified Paths: -------------- gfarm_v2/trunk/gftool/Makefile gfarm_v2/trunk/gftool/config-gfarm/gfarm.schema gfarm_v2/trunk/gftool/config-gfarm/gfarm.sql gfarm_v2/trunk/gftool/gfls/gfls.c gfarm_v2/trunk/gftool/gfstat/gfstat.c gfarm_v2/trunk/include/gfarm/gfs.h gfarm_v2/trunk/lib/libgfarm/gfarm/Makefile gfarm_v2/trunk/lib/libgfarm/gfarm/gfm_client.c gfarm_v2/trunk/lib/libgfarm/gfarm/gfm_client.h gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_dircache.c gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_io.c gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_pio.c gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_stat.c gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_statsw.c gfarm_v2/trunk/lib/libgfarm/gfarm/lookup.c gfarm_v2/trunk/regress/gftool/gfreg/gfreg.sh gfarm_v2/trunk/server/gfmd/db_access.c gfarm_v2/trunk/server/gfmd/db_access.h gfarm_v2/trunk/server/gfmd/db_common.c gfarm_v2/trunk/server/gfmd/db_common.h gfarm_v2/trunk/server/gfmd/db_ldap.c gfarm_v2/trunk/server/gfmd/db_none.c gfarm_v2/trunk/server/gfmd/db_ops.h gfarm_v2/trunk/server/gfmd/db_pgsql.c gfarm_v2/trunk/server/gfmd/fs.c gfarm_v2/trunk/server/gfmd/gfmd.c gfarm_v2/trunk/server/gfmd/inode.c gfarm_v2/trunk/server/gfmd/inode.h Added Paths: ----------- gfarm_v2/trunk/gftool/gfln/ gfarm_v2/trunk/gftool/gfln/Makefile gfarm_v2/trunk/gftool/gfln/gfln.c gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_readlink.c gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_symlink.c gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_util.c Modified: gfarm_v2/trunk/gftool/Makefile =================================================================== --- gfarm_v2/trunk/gftool/Makefile 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/gftool/Makefile 2009-03-12 20:57:02 UTC (rev 4085) @@ -13,6 +13,7 @@ gfgroup \ gfhost \ gfkey \ + gfln \ gfls \ gfmkdir \ gfmv \ Modified: gfarm_v2/trunk/gftool/config-gfarm/gfarm.schema =================================================================== --- gfarm_v2/trunk/gftool/config-gfarm/gfarm.schema 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/gftool/config-gfarm/gfarm.schema 2009-03-12 20:57:02 UTC (rev 4085) @@ -100,6 +100,9 @@ EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) +attributetype ( 1.3.6.1.4.1.13122.2.1.2924.100.2.28 NAME 'sourcePath' + EQUALITY caseExactMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE ) # Object Class Definitions # 1.3.6.1.4.1.13122.2.1.2924.101.3.x @@ -139,3 +142,7 @@ objectclass ( 1.3.6.1.4.1.13122.2.1.2924.101.3.5 NAME 'GFarmDirEntry' SUP top STRUCTURAL MUST ( inumber $ entryName $ entryINumber ) ) + +objectclass ( 1.3.6.1.4.1.13122.2.1.2924.101.3.8 + NAME 'GFarmSymlink' SUP top STRUCTURAL + MUST ( inumber $ sourcePath ) ) Modified: gfarm_v2/trunk/gftool/config-gfarm/gfarm.sql =================================================================== --- gfarm_v2/trunk/gftool/config-gfarm/gfarm.sql 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/gftool/config-gfarm/gfarm.sql 2009-03-12 20:57:02 UTC (rev 4085) @@ -84,3 +84,8 @@ ); CREATE INDEX dirEntryByINode ON DirEntry (dirINumber); + +CREATE TABLE Symlink ( + inumber INT8 PRIMARY KEY, + sourcePath VARCHAR(1024) NOT NULL +); Added: gfarm_v2/trunk/gftool/gfln/Makefile =================================================================== --- gfarm_v2/trunk/gftool/gfln/Makefile (rev 0) +++ gfarm_v2/trunk/gftool/gfln/Makefile 2009-03-12 20:57:02 UTC (rev 4085) @@ -0,0 +1,22 @@ +# $Id: Makefile 2612 2006-05-29 04:24:37Z soda $ + +top_builddir = ../.. +top_srcdir = $(top_builddir) +srcdir = . + +include $(top_srcdir)/makes/var.mk + +PROGRAM = gfln +SRCS = $(PROGRAM).c +OBJS = $(PROGRAM).o +CFLAGS = $(COMMON_CFLAGS) +LDLIBS = $(COMMON_LDLIBS) $(GFARMLIB) $(LIBS) +DEPLIBS = $(DEPGFARMLIB) + +all: $(PROGRAM) + +include $(top_srcdir)/makes/prog.mk + +### + +$(OBJS): $(DEPGFARMINC) Added: gfarm_v2/trunk/gftool/gfln/gfln.c =================================================================== --- gfarm_v2/trunk/gftool/gfln/gfln.c (rev 0) +++ gfarm_v2/trunk/gftool/gfln/gfln.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -0,0 +1,68 @@ +/* + * $Id: gfmv.c 2640 2006-05-29 22:38:29Z soda $ + */ + +#include <stdio.h> +#include <stdlib.h> +#include <libgen.h> +#include <unistd.h> + +#include <gfarm/gfarm.h> + +char *program_name = "gfln"; + +static void +usage(void) +{ + fprintf(stderr, "Usage: %s [-s] src dst\n", program_name); + exit(1); +} + +int +main(int argc, char **argv) +{ + gfarm_error_t e; + int c, status = 0; + int opt_symlink = 0; + extern int optind; + + if (argc > 0) + program_name = basename(argv[0]); + e = gfarm_initialize(&argc, &argv); + if (e != GFARM_ERR_NO_ERROR) { + fprintf(stderr, "%s: %s\n", program_name, + gfarm_error_string(e)); + exit(1); + } + + while ((c = getopt(argc, argv, "sh?")) != -1) { + switch (c) { + case 's': + opt_symlink = 1; + break; + case 'h': + case '?': + default: + usage(); + } + } + argc -= optind; + argv += optind; + if (argc != 2) + usage(); + + e = (opt_symlink ? gfs_symlink : gfs_link)(argv[0], argv[1]); + if (e != GFARM_ERR_NO_ERROR) { + fprintf(stderr, "%s%s %s %s: %s\n", + program_name, opt_symlink ? " -s" : "", + argv[0], argv[1], gfarm_error_string(e)); + status = 1; + } + e = gfarm_terminate(); + if (e != GFARM_ERR_NO_ERROR) { + fprintf(stderr, "%s: %s\n", program_name, + gfarm_error_string(e)); + status = 1; + } + return (status); +} Modified: gfarm_v2/trunk/gftool/gfls/gfls.c =================================================================== --- gfarm_v2/trunk/gftool/gfls/gfls.c 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/gftool/gfls/gfls.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -53,7 +53,7 @@ */ struct ls_entry { - char *path; + char *path, *symlink; struct gfs_stat *st; }; @@ -169,7 +169,7 @@ memcpy(namep, files[i], space); namep[space] = '\0'; } - e = gfs_stat_cached(buffer, &stats[i]); + e = gfs_lstat_cached(buffer, &stats[i]); if (e != GFARM_ERR_NO_ERROR) { fprintf(stderr, "%s: %s\n", buffer, gfarm_error_string(e)); @@ -182,6 +182,10 @@ } ls[m].path = files[i]; ls[m].st = &stats[i]; + if (!GFARM_S_ISLNK(ls[m].st->st_mode) || + gfs_readlink(buffer, &ls[m].symlink) != GFARM_ERR_NO_ERROR) + ls[m].symlink = NULL; + m++; } *np = m; @@ -196,8 +200,10 @@ if (GFARM_S_ISDIR(st->st_mode)) { putchar('/'); return 1; - } - else if (GFARM_S_IS_PROGRAM(st->st_mode)) { + } else if (GFARM_S_ISLNK(st->st_mode)) { + putchar('@'); + return 1; + } else if (GFARM_S_IS_PROGRAM(st->st_mode)) { putchar('*'); return 1; } @@ -254,13 +260,14 @@ { if (GFARM_S_ISDIR(st->st_mode)) putchar('d'); + else if (GFARM_S_ISLNK(st->st_mode)) + putchar('l'); else putchar('-'); put_perm(st->st_mode >> 6); put_perm(st->st_mode >> 3); put_perm(st->st_mode); - putchar(' '); - printf("%-8s %-8s ", st->st_user, st->st_group); + printf(" %d %-8s %-8s ", (int)st->st_nlink, st->st_user, st->st_group); printf("%10" GFARM_PRId64 " ", st->st_size); put_time(&st->st_mtimespec); putchar(' '); @@ -290,6 +297,7 @@ for (i = 0; i < n; i++) { ls[i].path = files[i]; ls[i].st = NULL; + ls[i].symlink = NULL; } } ls_sort(n, ls); @@ -339,6 +347,9 @@ fputs(ls[i].path, stdout); if (option_type_suffix) (void)put_suffix(&ls[i]); + if (option_output_format == OF_LONG && + ls[i].symlink != NULL) + printf(" -> %s", ls[i].symlink); putchar('\n'); } } @@ -666,7 +677,7 @@ char *path = gfarm_stringlist_elem(&paths, last); - e = gfs_stat_cached(path, &s); + e = gfs_lstat_cached(path, &s); if (e != GFARM_ERR_NO_ERROR) { fprintf(stderr, "%s: %s\n", path, gfarm_error_string(e)); @@ -678,8 +689,7 @@ types.length--; } else { GFS_GLOB_ELEM(types, last) = - GFARM_S_ISDIR(s.st_mode) ? - GFS_DT_DIR : GFS_DT_REG; + gfs_mode_to_type(s.st_mode); gfs_stat_free(&s); } } Modified: gfarm_v2/trunk/gftool/gfstat/gfstat.c =================================================================== --- gfarm_v2/trunk/gftool/gfstat/gfstat.c 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/gftool/gfstat/gfstat.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -28,6 +28,9 @@ case GFARM_S_IFDIR: puts("directory"); break; + case GFARM_S_IFLNK: + puts("symbolic link"); + break; default: printf("unknown\n"); } Modified: gfarm_v2/trunk/include/gfarm/gfs.h =================================================================== --- gfarm_v2/trunk/include/gfarm/gfs.h 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/include/gfarm/gfs.h 2009-03-12 20:57:02 UTC (rev 4085) @@ -21,14 +21,10 @@ #define GFARM_S_IFMT 0170000 /* type of file mask */ #define GFARM_S_IFDIR 0040000 /* directory */ #define GFARM_S_IFREG 0100000 /* regular file */ -#if 0 #define GFARM_S_IFLNK 0120000 /* symbolic link */ -#endif #define GFARM_S_ISDIR(m) (((m) & GFARM_S_IFMT) == GFARM_S_IFDIR) #define GFARM_S_ISREG(m) (((m) & GFARM_S_IFMT) == GFARM_S_IFREG) -#if 0 #define GFARM_S_ISLNK(m) (((m) & GFARM_S_IFMT) == GFARM_S_IFLNK) -#endif #define GFARM_S_IS_PROGRAM(m) \ (GFARM_S_ISREG(m) && ((m) & 0111) != 0) @@ -187,6 +183,8 @@ #define GFS_DT_UNKNOWN 0 /* gfs_hook.c depends on it that this is 0 */ #define GFS_DT_DIR 4 #define GFS_DT_REG 8 +#define GFS_DT_LNK 10 +int gfs_mode_to_type(gfarm_mode_t); typedef struct gfs_dir *GFS_Dir; @@ -206,6 +204,12 @@ gfarm_error_t gfs_realpath(const char *, char **); /* + * Symbolic link operations + */ +gfarm_error_t gfs_symlink(const char *, const char *); +gfarm_error_t gfs_readlink(const char *, char **); + +/* * Meta operations */ @@ -228,6 +232,7 @@ gfarm_error_t gfs_rename(const char *, const char *); gfarm_error_t gfs_stat(const char *, struct gfs_stat *); +gfarm_error_t gfs_lstat(const char *, struct gfs_stat *); gfarm_error_t gfs_fstat(GFS_File, struct gfs_stat *); #if 0 gfarm_error_t gfs_stat_section(const char *, const char *, struct gfs_stat *); @@ -264,6 +269,8 @@ gfarm_error_t gfs_stat_cache_purge(const char *); gfarm_error_t gfs_stat_cached(const char *, struct gfs_stat *); gfarm_error_t gfs_stat_caching(const char *, struct gfs_stat *); +gfarm_error_t gfs_lstat_cached(const char *, struct gfs_stat *); +gfarm_error_t gfs_lstat_caching(const char *, struct gfs_stat *); typedef struct gfs_dir_caching *GFS_DirCaching; gfarm_error_t gfs_opendir_caching(const char *, GFS_DirCaching *); Modified: gfarm_v2/trunk/lib/libgfarm/gfarm/Makefile =================================================================== --- gfarm_v2/trunk/lib/libgfarm/gfarm/Makefile 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/lib/libgfarm/gfarm/Makefile 2009-03-12 20:57:02 UTC (rev 4085) @@ -54,12 +54,15 @@ gfs_statfs.c \ gfs_statsw.c \ gfs_mkdir.c \ - gfs_rmdir.c \ + gfs_readlink.c \ gfs_remove.c \ gfs_rename.c \ gfs_replica.c \ gfs_replicate.c \ + gfs_rmdir.c \ + gfs_symlink.c \ gfs_unlink.c \ + gfs_util.c \ gfs_utimes.c \ gfarm_foreach.c \ glob.c \ @@ -115,12 +118,15 @@ gfs_statfs.lo \ gfs_statsw.lo \ gfs_mkdir.lo \ - gfs_rmdir.lo \ + gfs_readlink.lo \ gfs_remove.lo \ gfs_rename.lo \ gfs_replica.lo \ gfs_replicate.lo \ + gfs_rmdir.lo \ + gfs_symlink.lo \ gfs_unlink.lo \ + gfs_util.lo \ gfs_utimes.lo \ gfarm_foreach.lo \ glob.lo \ @@ -173,10 +179,12 @@ gfs_pio_remote.lo: host.h config.h gfs_proto.h gfs_client.h gfs_pio.h gfs_pio_section.lo: gfs_pio.h host.h config.h schedule.h gfs_client.h gfs_proto.h $(GFUTIL_SRCDIR)/timer.h gfs_proto.lo: gfs_proto.h +gfs_readlink.lo: $(GFUTIL_SRCDIR)/gfutil.h gfm_client.h config.h lookup.h gfs_replica.lo: $(GFUTIL_SRCDIR)/gfutil.h gfm_client.h config.h lookup.h gfs_replicate.lo: $(GFUTIL_SRCDIR)/gfutil.h config.h gfs_client.h gfs_stat.lo: $(GFUTIL_SRCDIR)/gfutil.h $(GFUTIL_SRCDIR)/timer.h gfs_profile.h gfm_client.h config.h lookup.h gfs_statsw.lo: gfs_dircache.h +gfs_symlink.lo: $(GFUTIL_SRCDIR)/gfutil.h gfm_client.h config.h lookup.h gfs_unlink.lo: config.h gfs_client.h gfs_pio.h gfs_misc.h $(GFUTIL_SRCDIR)/timer.h gfs_utimes.lo: $(GFUTIL_SRCDIR)/gfutil.h config.h gfm_client.h lookup.h gfarm_foreach.lo: gfarm_foreach.h Modified: gfarm_v2/trunk/lib/libgfarm/gfarm/gfm_client.c =================================================================== --- gfarm_v2/trunk/lib/libgfarm/gfarm/gfm_client.c 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/lib/libgfarm/gfarm/gfm_client.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -1267,8 +1267,7 @@ sz = sizeof(dirents[i].d_name) - 1; dirents[i].d_name[sz] = '\0'; dirents[i].d_namlen = sz; - dirents[i].d_type = GFARM_S_ISDIR(st->st_mode) ? - GFS_DT_DIR : GFS_DT_REG; + dirents[i].d_type = gfs_mode_to_type(st->st_mode); /* XXX */ dirents[i].d_reclen = sizeof(dirents[i]) - sizeof(dirents[i].d_name) + sz; Modified: gfarm_v2/trunk/lib/libgfarm/gfarm/gfm_client.h =================================================================== --- gfarm_v2/trunk/lib/libgfarm/gfarm/gfm_client.h 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/lib/libgfarm/gfarm/gfm_client.h 2009-03-12 20:57:02 UTC (rev 4085) @@ -185,7 +185,7 @@ gfarm_error_t gfm_client_symlink_request(struct gfm_connection *, const char *, const char *); gfarm_error_t gfm_client_symlink_result(struct gfm_connection *); -gfarm_error_t gfm_client_readlink(struct gfm_connection *); +gfarm_error_t gfm_client_readlink_request(struct gfm_connection *); gfarm_error_t gfm_client_readlink_result(struct gfm_connection *, char **); gfarm_error_t gfm_client_getdirpath_request(struct gfm_connection *); gfarm_error_t gfm_client_getdirpath_result(struct gfm_connection *, char **); Modified: gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_dircache.c =================================================================== --- gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_dircache.c 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_dircache.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -235,6 +235,13 @@ return (GFARM_ERR_NO_ERROR); } +/* this returns uncached result, but enter the result to the cache */ +gfarm_error_t +gfs_lstat_caching(const char *path, struct gfs_stat *st) +{ + return (gfs_stat_caching(path, st)); /* XXX FIXME */ +} + /* this returns cached result */ gfarm_error_t gfs_stat_cached_internal(const char *path, struct gfs_stat *st) Modified: gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_io.c =================================================================== --- gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_io.c 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_io.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -2,7 +2,7 @@ #include <stdio.h> /* config.h needs FILE */ #include <unistd.h> -#define GFARM_INTERNAL_USE +#define GFARM_INTERNAL_USE /* GFARM_FILE_LOOKUP */ #include <gfarm/gfarm.h> #include "gfutil.h" @@ -67,7 +67,7 @@ &inum, &gen, &mode); if (e != GFARM_ERR_NO_ERROR) return (e); - type = GFARM_S_ISDIR(mode) ? GFS_DT_DIR : GFS_DT_REG; + type = gfs_mode_to_type(mode); } e = gfm_client_get_fd_result(gfm_server, fdp); if (e != GFARM_ERR_NO_ERROR) @@ -145,10 +145,12 @@ gflog_warning("compound_begin result: %s", gfarm_error_string(e)); else if ((e = gfm_open_result(gfarm_metadb_server, url, - fdp, typep)) != GFARM_ERR_NO_ERROR) + fdp, typep)) != GFARM_ERR_NO_ERROR) { +#if 0 gflog_warning("open path result: %s", gfarm_error_string(e)); - else if ((e = gfm_client_compound_end_result(gfarm_metadb_server)) +#endif + } else if ((e = gfm_client_compound_end_result(gfarm_metadb_server)) != GFARM_ERR_NO_ERROR) gflog_warning("compound_end result: %s", gfarm_error_string(e)); Modified: gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_pio.c =================================================================== --- gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_pio.c 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_pio.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -187,7 +187,9 @@ ; else if (type != GFS_DT_REG) { (void)gfm_close_fd(fd); /* ignore this result */ - e = GFARM_ERR_IS_A_DIRECTORY; + e = type == GFS_DT_DIR ? GFARM_ERR_IS_A_DIRECTORY : + type == GFS_DT_LNK ? GFARM_ERR_IS_A_SYMBOLIC_LINK : + GFARM_ERR_OPERATION_NOT_PERMITTED; } else if ((e = gfs_file_alloc(fd, flags, gfp)) != GFARM_ERR_NO_ERROR) (void)gfm_close_fd(fd); /* ignore this result */ @@ -210,7 +212,9 @@ ; else if (type != GFS_DT_REG) { (void)gfm_close_fd(fd); /* ignore this result */ - e = GFARM_ERR_IS_A_DIRECTORY; + e = type == GFS_DT_DIR ? GFARM_ERR_IS_A_DIRECTORY : + type == GFS_DT_LNK ? GFARM_ERR_IS_A_SYMBOLIC_LINK : + GFARM_ERR_OPERATION_NOT_PERMITTED; } else if ((e = gfs_file_alloc(fd, flags, gfp)) != GFARM_ERR_NO_ERROR) (void)gfm_close_fd(fd); /* ignore this result */ Added: gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_readlink.c =================================================================== --- gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_readlink.c (rev 0) +++ gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_readlink.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -0,0 +1,64 @@ +#include <stddef.h> +#include <stdlib.h> + +#define GFARM_INTERNAL_USE +#include <gfarm/gfarm.h> + +#include "gfutil.h" + +#include "gfm_client.h" +#include "config.h" +#include "lookup.h" + +gfarm_error_t +gfs_readlink(const char *path, char **srcp) +{ + gfarm_error_t e; + + if ((e = gfm_client_compound_begin_request(gfarm_metadb_server)) + != GFARM_ERR_NO_ERROR) + gflog_warning("compound_begin request: %s", + gfarm_error_string(e)); + else if ((e = gfm_tmp_open_request(gfarm_metadb_server, path, + GFARM_FILE_LOOKUP)) != GFARM_ERR_NO_ERROR) + gflog_warning("tmp_open(%s) request: %s", path, + gfarm_error_string(e)); + else if ((e = gfm_client_readlink_request(gfarm_metadb_server)) + != GFARM_ERR_NO_ERROR) + gflog_warning("readlink request: %s", + gfarm_error_string(e)); + else if ((e = gfm_client_compound_end_request(gfarm_metadb_server)) + != GFARM_ERR_NO_ERROR) + gflog_warning("compound_end request: %s", + gfarm_error_string(e)); + + else if ((e = gfm_client_compound_begin_result(gfarm_metadb_server)) + != GFARM_ERR_NO_ERROR) + gflog_warning("compound_begin result: %s", + gfarm_error_string(e)); + else if ((e = gfm_tmp_open_result(gfarm_metadb_server, path, NULL)) + != GFARM_ERR_NO_ERROR) +#if 0 + gflog_warning("tmp_open(%s) result: %s", path, + gfarm_error_string(e)); +#else + ; +#endif + else if ((e = gfm_client_readlink_result(gfarm_metadb_server, srcp)) + != GFARM_ERR_NO_ERROR) +#if 0 + gflog_warning("readlink result: %s", + gfarm_error_string(e)); +#else + ; +#endif + else if ((e = gfm_client_compound_end_result(gfarm_metadb_server)) + != GFARM_ERR_NO_ERROR) { + gflog_warning("compound_end result: %s", + gfarm_error_string(e)); + free(*srcp); + } + /* NOTE: the opened descriptor is automatically closed by gfmd */ + + return (e); +} Modified: gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_stat.c =================================================================== --- gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_stat.c 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_stat.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -1,5 +1,5 @@ -#include <stdio.h> /* config.h needs FILE */ -#include <stdlib.h> +#include <stddef.h> +#include <unistd.h> #include <sys/time.h> #define GFARM_INTERNAL_USE @@ -76,6 +76,12 @@ } gfarm_error_t +gfs_lstat(const char *path, struct gfs_stat *s) +{ + return (gfs_stat(path, s)); /* XXX FIXME */ +} + +gfarm_error_t gfs_fstat(GFS_File gf, struct gfs_stat *s) { gfarm_error_t e; Modified: gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_statsw.c =================================================================== --- gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_statsw.c 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_statsw.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -64,6 +64,12 @@ return ((*gfs_statsw->stat)(path, st)); } +gfarm_error_t +gfs_lstat_cached(const char *path, struct gfs_stat *st) +{ + return ((*gfs_statsw->stat)(path, st)); /* XXX FIXME */ +} + void gfs_stat_cache_enable(int enable) { Added: gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_symlink.c =================================================================== --- gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_symlink.c (rev 0) +++ gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_symlink.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -0,0 +1,80 @@ +#include <stddef.h> +#include <unistd.h> + +#define GFARM_INTERNAL_USE +#include <gfarm/gfarm.h> + +#include "gfutil.h" + +#include "gfm_client.h" +#include "config.h" +#include "lookup.h" + +gfarm_error_t +gfs_symlink(const char *src, const char *dst) +{ + gfarm_error_t e, e_save = GFARM_ERR_NO_ERROR; + const char *dbase; + + if ((e = gfm_client_compound_begin_request(gfarm_metadb_server)) + != GFARM_ERR_NO_ERROR) + gflog_warning("compound_begin request: %s", + gfarm_error_string(e)); + else if ((e = gfm_lookup_dir_request(gfarm_metadb_server, + dst, &dbase)) != GFARM_ERR_NO_ERROR) + gflog_warning("lookup_dir(%s) request: %s", dst, + gfarm_error_string(e)); + else { + /* "/" is special */ + if (dbase[0] == '/' && dbase[1] == '\0') + e_save = GFARM_ERR_OPERATION_NOT_PERMITTED; + else if ((e = gfm_client_symlink_request( + gfarm_metadb_server, src, dbase)) != GFARM_ERR_NO_ERROR) + gflog_warning("symlink request: %s", + gfarm_error_string(e)); + } + if (e != GFARM_ERR_NO_ERROR) + return (e); + + if ((e = gfm_client_compound_end_request(gfarm_metadb_server)) + != GFARM_ERR_NO_ERROR) + gflog_warning("compound_end request: %s", + gfarm_error_string(e)); + + else if ((e = gfm_client_compound_begin_result(gfarm_metadb_server)) + != GFARM_ERR_NO_ERROR) + gflog_warning("compound_begin result: %s", + gfarm_error_string(e)); + else if ((e = gfm_lookup_dir_result(gfarm_metadb_server, + dst, &dbase)) != GFARM_ERR_NO_ERROR) +#if 0 /* DEBUG */ + gflog_warning("lookup_dir(%s) result: %s", dst, + gfarm_error_string(e)); +#else + ; +#endif + else { + /* "/" is special */ + if (dbase[0] == '/' && dbase[1] == '\0') + e_save = GFARM_ERR_OPERATION_NOT_PERMITTED; + else if ((e = gfm_client_symlink_result( + gfarm_metadb_server)) != GFARM_ERR_NO_ERROR) +#if 0 /* DEBUG */ + gflog_warning("symlink result: %s", + gfarm_error_string(e)); +#else + ; +#endif + } + if (e != GFARM_ERR_NO_ERROR) + return (e); + + if ((e = gfm_client_compound_end_result(gfarm_metadb_server)) + != GFARM_ERR_NO_ERROR) + gflog_warning("compound_end result: %s", + gfarm_error_string(e)); + + /* NOTE: the opened descriptor is automatically closed by gfmd */ + + return (e_save != GFARM_ERR_NO_ERROR ? e_save : e); +} Added: gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_util.c =================================================================== --- gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_util.c (rev 0) +++ gfarm_v2/trunk/lib/libgfarm/gfarm/gfs_util.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -0,0 +1,11 @@ +#include <stddef.h> +#include <gfarm/gfarm.h> + +int +gfs_mode_to_type(gfarm_mode_t mode) +{ + return (GFARM_S_ISDIR(mode) ? GFS_DT_DIR : + GFARM_S_ISREG(mode) ? GFS_DT_REG : + GFARM_S_ISLNK(mode) ? GFS_DT_LNK : + GFS_DT_UNKNOWN); +} Modified: gfarm_v2/trunk/lib/libgfarm/gfarm/lookup.c =================================================================== --- gfarm_v2/trunk/lib/libgfarm/gfarm/lookup.c 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/lib/libgfarm/gfarm/lookup.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -2,7 +2,7 @@ #include <string.h> #include <unistd.h> -#define GFARM_INTERNAL_USE +#define GFARM_INTERNAL_USE /* GFARM_FILE_LOOKUP, gfs_mode_to_type(), etc. */ #include <gfarm/error.h> #include <gfarm/gfarm_misc.h> #include <gfarm/gfs.h> @@ -169,7 +169,7 @@ &inum, &gen, &mode); if (e != GFARM_ERR_NO_ERROR) return (e); - type = GFARM_S_ISDIR(mode) ? GFS_DT_DIR : GFS_DT_REG; + type = gfs_mode_to_type(mode); } if (typep != NULL) *typep = type; Modified: gfarm_v2/trunk/regress/gftool/gfreg/gfreg.sh =================================================================== --- gfarm_v2/trunk/regress/gftool/gfreg/gfreg.sh 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/regress/gftool/gfreg/gfreg.sh 2009-03-12 20:57:02 UTC (rev 4085) @@ -13,7 +13,7 @@ datasize=`ls -l $datafile | awk '{print $5}'` if gfreg $datafile $gftmp && [ x"`gfls $gftmp`" = x"$gftmp" ] && - [ x"`gfls -l $gftmp | awk '{print $4}'`" = x"$datasize" ]; then + [ x"`gfls -l $gftmp | awk '{print $5}'`" = x"$datasize" ]; then exit_code=$exit_pass fi Modified: gfarm_v2/trunk/server/gfmd/db_access.c =================================================================== --- gfarm_v2/trunk/server/gfmd/db_access.c 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/server/gfmd/db_access.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -901,3 +901,48 @@ { return ((*ops->direntry_load)(closure, callback)); } + +struct db_symlink_arg * +db_symlink_arg_alloc(gfarm_ino_t inum, const char *source_path) +{ + struct db_symlink_arg *arg = + malloc(sizeof(*arg) + strlen(source_path) + 1); + + if (arg == NULL) + return (NULL); + arg->source_path = (char *)arg + sizeof(*arg); + + arg->inum = inum; + strcpy(arg->source_path, source_path); + return (arg); +} + +gfarm_error_t +db_symlink_add(gfarm_ino_t inum, const char *source_path) +{ + struct db_symlink_arg *arg = + db_symlink_arg_alloc(inum, source_path); + + if (arg == NULL) + return (GFARM_ERR_NO_MEMORY); + return (dbq_enter(&dbq, (dbq_entry_func_t)ops->symlink_add, arg)); +} + +gfarm_error_t +db_symlink_remove(gfarm_ino_t inum) +{ + struct db_inode_inum_arg *arg; + + GFARM_MALLOC(arg); + if (arg == NULL) + return (GFARM_ERR_NO_MEMORY); + arg->inum = inum; + return (dbq_enter(&dbq, (dbq_entry_func_t)ops->symlink_remove, arg)); +} + +gfarm_error_t +db_symlink_load(void *closure, void (*callback)(void *, gfarm_ino_t, char *)) +{ + return ((*ops->symlink_load)(closure, callback)); +} + Modified: gfarm_v2/trunk/server/gfmd/db_access.h =================================================================== --- gfarm_v2/trunk/server/gfmd/db_access.h 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/server/gfmd/db_access.h 2009-03-12 20:57:02 UTC (rev 4085) @@ -79,7 +79,11 @@ gfarm_error_t db_direntry_load(void *, void (*)(void *, gfarm_ino_t, char *, int, gfarm_ino_t)); +gfarm_error_t db_symlink_add(gfarm_ino_t, const char *); +gfarm_error_t db_symlink_remove(gfarm_ino_t); +gfarm_error_t db_symlink_load(void *, void (*)(void *, gfarm_ino_t, char *)); + /* external interface to select metadb backend type */ struct db_ops; Modified: gfarm_v2/trunk/server/gfmd/db_common.c =================================================================== --- gfarm_v2/trunk/server/gfmd/db_common.c 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/server/gfmd/db_common.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -197,3 +197,48 @@ db_direntry_arg_clear, db_direntry_arg_validate, }; + +/**********************************************************************/ + +static void +db_symlink_arg_free(void *vinfo) +{ + struct db_symlink_arg *info = vinfo; + + if (info->source_path != NULL) + free(info->source_path); +} + +static void +db_symlink_arg_clear(void *vinfo) +{ + struct db_symlink_arg *info = vinfo; + + memset(info, 0, sizeof(*info)); +} + +static int +db_symlink_arg_validate(void *vinfo) +{ + struct db_symlink_arg *info = vinfo; + + return ( + info->source_path != NULL + ); +} + +void +db_symlink_callback_trampoline(void *closure, void *vinfo) +{ + struct db_symlink_trampoline_closure *c = closure; + struct db_symlink_arg *info = vinfo; + + (*c->callback)(c->closure, info->inum, info->source_path); +} + +const struct gfarm_base_generic_info_ops db_base_symlink_arg_ops = { + sizeof(struct db_symlink_arg), + db_symlink_arg_free, + db_symlink_arg_clear, + db_symlink_arg_validate, +}; Modified: gfarm_v2/trunk/server/gfmd/db_common.h =================================================================== --- gfarm_v2/trunk/server/gfmd/db_common.h 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/server/gfmd/db_common.h 2009-03-12 20:57:02 UTC (rev 4085) @@ -18,13 +18,20 @@ void (*callback)(void *, gfarm_ino_t, char *, int, gfarm_ino_t); }; +struct db_symlink_trampoline_closure { + void *closure; + void (*callback)(void *, gfarm_ino_t, char *); +}; + extern const struct gfarm_base_generic_info_ops db_base_inode_cksum_arg_ops, db_base_filecopy_arg_ops, db_base_deadfilecopy_arg_ops, - db_base_direntry_arg_ops; + db_base_direntry_arg_ops, + db_base_symlink_arg_ops; void db_inode_cksum_callback_trampoline(void *, void *); void db_filecopy_callback_trampoline(void *, void *); void db_deadfilecopy_callback_trampoline(void *, void *); void db_direntry_callback_trampoline(void *, void *); +void db_symlink_callback_trampoline(void *, void *); Modified: gfarm_v2/trunk/server/gfmd/db_ldap.c =================================================================== --- gfarm_v2/trunk/server/gfmd/db_ldap.c 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/server/gfmd/db_ldap.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -1380,14 +1380,10 @@ /**********************************************************************/ -static char *gfarm_ldap_inode_make_dn(void *vkey); +static char *gfarm_ldap_db_inode_inum_make_dn(void *vkey); static void gfarm_ldap_gfs_stat_set_field(void *info, char *attribute, char **vals); -struct gfarm_ldap_inode_key { - gfarm_ino_t inumber; -}; - static char INODE_QUERY_TYPE[] = "(objectclass=GFarmINode)"; static char INODE_DN_TEMPLATE[] = "inumber=%" GFARM_PRId64 ", %s"; @@ -1395,14 +1391,14 @@ &gfarm_base_gfs_stat_ops, INODE_QUERY_TYPE, INODE_DN_TEMPLATE, - gfarm_ldap_inode_make_dn, + gfarm_ldap_db_inode_inum_make_dn, gfarm_ldap_gfs_stat_set_field, }; static char * -gfarm_ldap_inode_make_dn(void *vkey) +gfarm_ldap_db_inode_inum_make_dn(void *vkey) { - struct gfarm_ldap_inode_key *key = vkey; + struct db_inode_inum_arg *key = vkey; char *dn; GFARM_MALLOC_ARRAY(dn, strlen(gfarm_ldap_gfs_stat_ops.dn_template) + @@ -1410,7 +1406,7 @@ if (dn == NULL) return (NULL); sprintf(dn, gfarm_ldap_gfs_stat_ops.dn_template, - key->inumber, gfarm_ldap_base_dn); + key->inum, gfarm_ldap_base_dn); return (dn); } @@ -1475,9 +1471,9 @@ char ctime_sec_string[INT64STRLEN + 1]; char ctime_nsec_string[INT32STRLEN + 1]; - struct gfarm_ldap_inode_key key; + struct db_inode_inum_arg key; - key.inumber = info->st_ino; + key.inum = info->st_ino; sprintf(ino_string, "%" GFARM_PRId64, info->st_ino); sprintf(igen_string, "%" GFARM_PRId64, info->st_gen); @@ -1568,9 +1564,9 @@ char ino_string[INT64STRLEN + 1]; char uint64_string[INT64STRLEN + 1]; - struct gfarm_ldap_inode_key key; + struct db_inode_inum_arg key; - key.inumber = arg->inum; + key.inum = arg->inum; sprintf(ino_string, "%" GFARM_PRId64, arg->inum); sprintf(uint64_string, "%" GFARM_PRId64, arg->uint64); @@ -1600,9 +1596,9 @@ char ino_string[INT64STRLEN + 1]; - struct gfarm_ldap_inode_key key; + struct db_inode_inum_arg key; - key.inumber = arg->inum; + key.inum = arg->inum; sprintf(ino_string, "%" GFARM_PRId64, arg->inum); @@ -1634,9 +1630,9 @@ char sec_string[INT64STRLEN + 1]; char nsec_string[INT32STRLEN + 1]; - struct gfarm_ldap_inode_key key; + struct db_inode_inum_arg key; - key.inumber = arg->inum; + key.inum = arg->inum; sprintf(ino_string, "%" GFARM_PRId64, arg->inum); sprintf(sec_string, "%" GFARM_PRId64, arg->time.tv_sec); @@ -1683,9 +1679,9 @@ char ino_string[INT64STRLEN + 1]; char mode_string[INT32STRLEN + 1]; - struct gfarm_ldap_inode_key key; + struct db_inode_inum_arg key; - key.inumber = arg->inum; + key.inum = arg->inum; sprintf(ino_string, "%" GFARM_PRId64, arg->inum); sprintf(mode_string, "%07o", arg->uint32); @@ -1757,7 +1753,7 @@ &db_base_inode_cksum_arg_ops, INODE_QUERY_TYPE, INODE_DN_TEMPLATE, - gfarm_ldap_inode_make_dn, + gfarm_ldap_db_inode_inum_make_dn, gfarm_ldap_inode_cksum_set_field, }; @@ -1790,9 +1786,9 @@ LDAPMod *modv[3]; struct ldap_string_modify storage[ARRAY_LENGTH(modv) - 1]; - struct gfarm_ldap_inode_key key; + struct db_inode_inum_arg key; - key.inumber = info->inum; + key.inum = info->inum; i = 0; set_string_mod(&modv[i], mod_op, @@ -1832,10 +1828,6 @@ LDAPMod *modv[3]; LDAPMod storage[ARRAY_LENGTH(modv) - 1]; - struct gfarm_ldap_inode_key key; - - key.inumber = arg->inum; - i = 0; set_delete_mod(&modv[i], "checksumType", &storage[i]); i++; @@ -1844,7 +1836,7 @@ modv[i++] = NULL; assert(i == ARRAY_LENGTH(modv)); - e = gfarm_ldap_generic_info_modify(&key, modv, + e = gfarm_ldap_generic_info_modify(arg, modv, &gfarm_ldap_inode_cksum_ops); free(arg); @@ -1985,6 +1977,7 @@ gfarm_ldap_db_deadfilecopy_ops = { &db_base_deadfilecopy_arg_ops, "(objectclass=GFarmDeadFileCopy)", + /* XXX FIXME - the following assumption is wrong: delay of removal */ /* There should not be two entries for the same inumber */ "hostname=%s, inumber=%" GFARM_PRId64 ", %s", gfarm_ldap_db_deadfilecopy_make_dn, @@ -2271,6 +2264,102 @@ /**********************************************************************/ +static void gfarm_ldap_db_symlink_set_field(void *info, char *attribute, + char **vals); + +static const struct gfarm_ldap_generic_info_ops + gfarm_ldap_db_symlink_ops = { + &db_base_symlink_arg_ops, + "(objectclass=GFarmSymlink)", + "inumber=%" GFARM_PRId64 ", %s", + gfarm_ldap_db_inode_inum_make_dn, + gfarm_ldap_db_symlink_set_field, +}; + +static void +gfarm_ldap_db_symlink_set_field( + void *vinfo, + char *attribute, + char **vals) +{ + struct db_symlink_arg *info = vinfo; + + if (strcasecmp(attribute, "inumber") == 0) { + info->inum = gfarm_strtoi64(vals[0], NULL); + } else if (strcasecmp(attribute, "sourcePath") == 0) { + info->source_path = strdup(vals[0]); + } +} + +static gfarm_error_t +gfarm_ldap_db_symlink_update( + struct db_symlink_arg *info, + int mod_op, + gfarm_error_t (*update_op)(void *, LDAPMod **, + const struct gfarm_ldap_generic_info_ops *)) +{ + int i; + LDAPMod *modv[4]; + struct ldap_string_modify storage[ARRAY_LENGTH(modv) - 1]; + + char ino_string[INT64STRLEN + 1]; + + struct db_inode_inum_arg key; + + key.inum = info->inum; + + sprintf(ino_string, "%" GFARM_PRId64, info->inum); + + i = 0; + set_string_mod(&modv[i], mod_op, + "objectclass", "GFarmSymlink", &storage[i]); + i++; + set_string_mod(&modv[i], mod_op, + "inumber", ino_string, &storage[i]); + i++; + set_string_mod(&modv[i], mod_op, + "sourcePath", info->source_path, &storage[i]); + i++; + modv[i++] = NULL; + assert(i == ARRAY_LENGTH(modv)); + + return ((*update_op)(&key, modv, &gfarm_ldap_db_symlink_ops)); +} + +static void +gfarm_ldap_symlink_add(struct db_symlink_arg *info) +{ + gfarm_ldap_db_symlink_update(info, + LDAP_MOD_ADD, gfarm_ldap_generic_info_add); + free(info); +} + +static void +gfarm_ldap_symlink_remove(struct db_inode_inum_arg *arg) +{ + gfarm_ldap_generic_info_remove(arg, &gfarm_ldap_db_symlink_ops); + free(arg); +} + +static gfarm_error_t +gfarm_ldap_symlink_load( + void *closure, + void (*callback)(void *, gfarm_ino_t, char *)) +{ + struct db_symlink_arg tmp_info; + struct db_symlink_trampoline_closure c; + + c.closure = closure; + c.callback = callback; + + return (gfarm_ldap_generic_info_get_foreach(gfarm_ldap_base_dn, + LDAP_SCOPE_ONELEVEL, gfarm_ldap_db_symlink_ops.query_type, + &tmp_info, db_symlink_callback_trampoline, &c, + &gfarm_ldap_db_symlink_ops)); +} + +/**********************************************************************/ + const struct db_ops db_ldap_ops = { gfarm_ldap_initialize, gfarm_ldap_terminate, @@ -2320,4 +2409,8 @@ gfarm_ldap_direntry_add, gfarm_ldap_direntry_remove, gfarm_ldap_direntry_load, + + gfarm_ldap_symlink_add, + gfarm_ldap_symlink_remove, + gfarm_ldap_symlink_load, }; Modified: gfarm_v2/trunk/server/gfmd/db_none.c =================================================================== --- gfarm_v2/trunk/server/gfmd/db_none.c 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/server/gfmd/db_none.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -160,13 +160,13 @@ /**********************************************************************/ static void -gfarm_none_inode_cksum_arg_free(struct db_inode_cksum_arg *arg) +gfarm_none_inode_cksum_free(struct db_inode_cksum_arg *arg) { free(arg); } static void -gfarm_none_inode_cksum_remove(struct db_inode_inum_arg *arg) +gfarm_none_inode_inum_free(struct db_inode_inum_arg *arg) { free(arg); } @@ -235,6 +235,22 @@ /**********************************************************************/ +static void +gfarm_none_symlink_free(struct db_symlink_arg *arg) +{ + free(arg); +} + +static gfarm_error_t +gfarm_none_symlink_load( + void *closure, + void (*callback)(void *, gfarm_ino_t, char *)) +{ + return (GFARM_ERR_OPERATION_NOT_SUPPORTED); +} + +/**********************************************************************/ + const struct db_ops db_none_ops = { gfarm_none_initialize, gfarm_none_terminate, @@ -268,9 +284,9 @@ gfarm_none_inode_load, /* cksum */ - gfarm_none_inode_cksum_arg_free, - gfarm_none_inode_cksum_arg_free, - gfarm_none_inode_cksum_remove, + gfarm_none_inode_cksum_free, + gfarm_none_inode_cksum_free, + gfarm_none_inode_inum_free, gfarm_none_inode_cksum_load, gfarm_none_filecopy_free, @@ -284,4 +300,8 @@ gfarm_none_direntry_add, gfarm_none_direntry_remove, gfarm_none_direntry_load, + + gfarm_none_symlink_free, + gfarm_none_inode_inum_free, + gfarm_none_symlink_load, }; Modified: gfarm_v2/trunk/server/gfmd/db_ops.h =================================================================== --- gfarm_v2/trunk/server/gfmd/db_ops.h 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/server/gfmd/db_ops.h 2009-03-12 20:57:02 UTC (rev 4085) @@ -85,6 +85,11 @@ int entry_len; }; +struct db_symlink_arg { + gfarm_ino_t inum; + char *source_path; +}; + struct db_ops { gfarm_error_t (*initialize)(void); gfarm_error_t (*terminate)(void); @@ -141,4 +146,10 @@ void (*direntry_remove)(struct db_direntry_arg *); gfarm_error_t (*direntry_load)(void *, void (*)(void *, gfarm_ino_t, char *, int, gfarm_ino_t)); + + void (*symlink_add)(struct db_symlink_arg *); + void (*symlink_remove)(struct db_inode_inum_arg *); + gfarm_error_t (*symlink_load)(void *, + void (*)(void *, gfarm_ino_t, char *)); + }; Modified: gfarm_v2/trunk/server/gfmd/db_pgsql.c =================================================================== --- gfarm_v2/trunk/server/gfmd/db_pgsql.c 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/server/gfmd/db_pgsql.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -1569,6 +1569,31 @@ } static void +pgsql_inode_inum_call(struct db_inode_inum_arg *arg, const char *sql, + gfarm_error_t (*op)(const char *, int, const Oid *, + const char *const *, const int *, const int *, int, + const char *), + const char *diag) +{ + const char *paramValues[1]; + char inumber[GFARM_INT64STRLEN + 1]; + + sprintf(inumber, "%" GFARM_PRId64, arg->inum); + paramValues[0] = inumber; + (*op)( + sql, + 1, /* number of params */ + NULL, /* param types */ + paramValues, + NULL, /* param lengths */ + NULL, /* param formats */ + 0, /* ask for text results */ + diag); + + free(arg); +} + +static void gfarm_pgsql_file_info_add(struct db_inode_cksum_arg *arg) { pgsql_inode_cksum_call(arg, @@ -1589,22 +1614,10 @@ static void gfarm_pgsql_file_info_remove(struct db_inode_inum_arg *arg) { - const char *paramValues[1]; - char inumber[GFARM_INT64STRLEN + 1]; - - sprintf(inumber, "%" GFARM_PRId64, arg->inum); - paramValues[0] = inumber; - gfarm_pgsql_update_or_delete_with_retry( + pgsql_inode_inum_call(arg, "DELETE FROM FileInfo WHERE inumber = $1", - 1, /* number of params */ - NULL, /* param types */ - paramValues, - NULL, /* param lengths */ - NULL, /* param formats */ - 0, /* ask for text results */ + gfarm_pgsql_update_or_delete_with_retry, "pgsql_cksum_remove"); - - free(arg); } static void @@ -1908,6 +1921,87 @@ /**********************************************************************/ +static void +pgsql_symlink_call(struct db_symlink_arg *arg, const char *sql, + gfarm_error_t (*op)(const char *, int, const Oid *, + const char *const *, const int *, const int *, int, + const char *), + const char *diag) +{ + const char *paramValues[2]; + char inumber[GFARM_INT64STRLEN + 1]; + + sprintf(inumber, "%" GFARM_PRId64, arg->inum); + paramValues[0] = inumber; + paramValues[1] = arg->source_path; + (*op)( + sql, + 2, /* number of params */ + NULL, /* param types */ + paramValues, + NULL, /* param lengths */ + NULL, /* param formats */ + 0, /* ask for text results */ + diag); + + free(arg); +} + +static void +gfarm_pgsql_symlink_add(struct db_symlink_arg *arg) +{ + pgsql_symlink_call(arg, + "INSERT INTO Symlink (inumber, sourcePath) VALUES ($1, $2)", + gfarm_pgsql_insert_with_retry, + "pgsql_symlink_add"); +} + +static void +gfarm_pgsql_symlink_remove(struct db_inode_inum_arg *arg) +{ + pgsql_inode_inum_call(arg, + "DELETE FROM Symlink WHERE inumber = $1", + gfarm_pgsql_update_or_delete_with_retry, + "pgsql_symlink_remove"); +} + +static void +symlink_set_fields_from_copy_binary( + const char *buf, int residual, void *vinfo) +{ + struct db_symlink_arg *info = vinfo; + uint16_t num_fields; + + COPY_BINARY(num_fields, buf, residual, + "pgsql_symlink_load: field number"); + num_fields = ntohs(num_fields); + if (num_fields < 2) /* allow fields addition in future */ + gflog_fatal("pgsql_symlink_load: fields = %d", num_fields); + + info->inum = get_value_from_int8_copy_binary(&buf, &residual); + info->source_path = get_value_from_varchar_copy_binary(&buf, &residual); +} + +static gfarm_error_t +gfarm_pgsql_symlink_load( + void *closure, + void (*callback)(void *, gfarm_ino_t, char *)) +{ + struct db_symlink_arg tmp_info; + struct db_symlink_trampoline_closure c; + + c.closure = closure; + c.callback = callback; + + return (gfarm_pgsql_generic_load( + "COPY Symlink TO STDOUT BINARY", + &tmp_info, db_symlink_callback_trampoline, &c, + &db_base_symlink_arg_ops, + symlink_set_fields_from_copy_binary, + "pgsql_symlink_load")); +} +/**********************************************************************/ + const struct db_ops db_pgsql_ops = { gfarm_pgsql_initialize, gfarm_pgsql_terminate, @@ -1957,4 +2051,8 @@ gfarm_pgsql_direntry_add, gfarm_pgsql_direntry_remove, gfarm_pgsql_direntry_load, + + gfarm_pgsql_symlink_add, + gfarm_pgsql_symlink_remove, + gfarm_pgsql_symlink_load, }; Modified: gfarm_v2/trunk/server/gfmd/fs.c =================================================================== --- gfarm_v2/trunk/server/gfmd/fs.c 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/server/gfmd/fs.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -929,6 +929,7 @@ { gfarm_error_t e; char *name; + struct host *spool_host = NULL; struct process *process; gfarm_int32_t sfd, dfd; struct inode *src, *base; @@ -942,8 +943,10 @@ } giant_lock(); - if ((process = peer_get_process(peer)) == NULL) + if (!from_client && (spool_host = peer_get_host(peer)) == NULL) e = GFARM_ERR_OPERATION_NOT_PERMITTED; + else if ((process = peer_get_process(peer)) == NULL) + e = GFARM_ERR_OPERATION_NOT_PERMITTED; else if (process_get_user(process) == NULL) e = GFARM_ERR_OPERATION_NOT_PERMITTED; else if ((e = peer_fdpair_get_saved(peer, &sfd)) != GFARM_ERR_NO_ERROR) @@ -951,8 +954,8 @@ else if ((e = process_get_file_inode(process, sfd, &src)) != GFARM_ERR_NO_ERROR) ; - else if (inode_is_dir(src)) - e = GFARM_ERR_IS_A_DIRECTORY; + else if (!inode_is_file(src)) + e = GFARM_ERR_OPERATION_NOT_PERMITTED; else if ((e = peer_fdpair_get_current(peer, &dfd)) != GFARM_ERR_NO_ERROR) ; @@ -1010,40 +1013,77 @@ gfm_server_symlink(struct peer *peer, int from_client, int skip) { gfarm_error_t e; - char *target, *name; + char *source_path, *name; + struct host *spool_host = NULL; + struct process *process; + gfarm_int32_t cfd; + struct inode *base; - /* XXX - NOT IMPLEMENTED */ - gflog_error("symlink: not implemented"); - - e = gfm_server_get_request(peer, "symlink", "ss", &target, &name); + e = gfm_server_get_request(peer, "symlink", "ss", &source_path, &name); if (e != GFARM_ERR_NO_ERROR) return (e); if (skip) { - free(target); + free(source_path); free(name); return (GFARM_ERR_NO_ERROR); } + giant_lock(); - free(target); + if (!from_client && (spool_host = peer_get_host(peer)) == NULL) + e = GFARM_ERR_OPERATION_NOT_PERMITTED; + else if ((process = peer_get_process(peer)) == NULL) + e = GFARM_ERR_OPERATION_NOT_PERMITTED; + else if (process_get_user(process) == NULL) + e = GFARM_ERR_OPERATION_NOT_PERMITTED; + else if ((e = peer_fdpair_get_current(peer, &cfd)) != + GFARM_ERR_NO_ERROR) + ; + else if ((e = process_get_file_inode(process, cfd, &base)) + != GFARM_ERR_NO_ERROR) + ; + else + e = inode_create_symlink(base, name, process, source_path); + + free(source_path); free(name); - e = gfm_server_put_reply(peer, "symlink", - GFARM_ERR_FUNCTION_NOT_IMPLEMENTED, ""); - return (e != GFARM_ERR_NO_ERROR ? e : - GFARM_ERR_FUNCTION_NOT_IMPLEMENTED); + giant_unlock(); + return (gfm_server_put_reply(peer, "symlink", e, "")); } gfarm_error_t gfm_server_readlink(struct peer *peer, int from_client, int skip) { - gfarm_error_t e; + gfarm_error_t e, e2; + gfarm_int32_t fd; + struct host *spool_host = NULL; + struct process *process; + struct inode *inode; + char *source_path = NULL; - /* XXX - NOT IMPLEMENTED */ - gflog_error("readlink: not implemented"); + if (skip) + return (GFARM_ERR_NO_ERROR); + giant_lock(); - e = gfm_server_put_reply(peer, "readlink", - GFARM_ERR_FUNCTION_NOT_IMPLEMENTED, ""); - return (e != GFARM_ERR_NO_ERROR ? e : - GFARM_ERR_FUNCTION_NOT_IMPLEMENTED); + if (!from_client && (spool_host = peer_get_host(peer)) == NULL) + e = GFARM_ERR_OPERATION_NOT_PERMITTED; + else if ((process = peer_get_process(peer)) == NULL) + e = GFARM_ERR_OPERATION_NOT_PERMITTED; + else if ((e = peer_fdpair_get_current(peer, &fd)) != + GFARM_ERR_NO_ERROR) + ; + else if ((e = process_get_file_inode(process, fd, &inode)) != + GFARM_ERR_NO_ERROR) + ; + else if ((source_path = inode_get_symlink(inode)) == NULL) + e = GFARM_ERR_INVALID_ARGUMENT; /* not a symlink */ + else if ((source_path = strdup(source_path)) == NULL) + e = GFARM_ERR_NO_MEMORY; + + giant_unlock(); + e2 = gfm_server_put_reply(peer, "readlink", e, "s", source_path); + if (e == GFARM_ERR_NO_ERROR) + free(source_path); + return (e2); } gfarm_error_t @@ -1193,8 +1233,8 @@ p[i].name == NULL) break; p[i].inum = inode_get_number(entry_inode); - p[i].type = inode_is_dir(entry_inode) ? - GFS_DT_DIR : GFS_DT_REG; + p[i].type = + gfs_mode_to_type(inode_get_mode(entry_inode)); i++; if (!dir_cursor_next(dir, &cursor)) Modified: gfarm_v2/trunk/server/gfmd/gfmd.c =================================================================== --- gfarm_v2/trunk/server/gfmd/gfmd.c 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/server/gfmd/gfmd.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -920,6 +920,7 @@ dir_entry_init(); file_copy_init(); dead_file_copy_init(); + symlink_init(); peer_init(table_size, protocol_main); job_table_init(table_size); Modified: gfarm_v2/trunk/server/gfmd/inode.c =================================================================== --- gfarm_v2/trunk/server/gfmd/inode.c 2009-03-12 15:24:39 UTC (rev 4084) +++ gfarm_v2/trunk/server/gfmd/inode.c 2009-03-12 20:57:02 UTC (rev 4085) @@ -66,6 +66,9 @@ struct inode_dir { Dir entries; } d; + struct inode_symlink { + char *source_path; + } l; } s; struct inode_open_state *state; } c; @@ -438,6 +441,8 @@ inode_cksum_remove(inode); } else if (inode_is_dir(inode)) { dir_free(inode->u.c.s.d.entries); + } else if (inode_is_symlink(inode)) { + free(inode->u.c.s.l.source_path); } else { gflog_fatal("inode_unlink: unknown inode type"); /*NOTREACHED*/ @@ -500,6 +505,20 @@ return (GFARM_ERR_NO_ERROR); } +gfarm_error_t +inode_init_symlink(struct inode *inode, char *source_path) +{ + if (source_path != NULL) { + source_path = strdup(source_path); + if (source_path == NULL) + return (GFARM_ERR_NO_MEMORY); + } + inode->i_nlink = 1; + inode->i_mode = GFARM_S_IFLNK; + inode->u.c.s.l.source_path = source_path; + return (GFARM_ERR_NO_ERROR); +} + struct inode * inode_lookup(gfarm_ino_t inum) { @@ -527,6 +546,12 @@ return (GFARM_S_ISREG(inode->i_mode)); } +int +inode_is_symlink(struct inode *inode) +{ + return (GFARM_S_ISLNK(inode->i_mode)); +} + gfarm_ino_t inode_get_number(struct inode *inode) { @@ -763,6 +788,14 @@ return (inode->u.c.s.d.entries); } +char * +inode_get_symlink(struct inode *inode) +{ + if (!inode_is_symlink(inode)) + return (NULL); + return (inode->u.c.s.l.source_path); +} + gfarm_error_t inode_access(struct inode *inode, struct user *user, int op) { @@ -797,14 +830,28 @@ enum gfarm_inode_lookup_op { INODE_LOOKUP, INODE_CREATE, + INODE_CREATE_EXCLUSIVE, INODE_REMOVE, INODE_LINK, }; -/* if (op != INODE_CREATE), (is_dir) may be -1, and that means "don't care". */ +/* + * if (op == INODE_LINK) + * (*inp) is an input parameter instead of output. + * if (op == INODE_CREATE) + * createdp must be passed, otherwise it's ignored. + * if (op != INODE_CREATE && op != INODE_CREATE_EXCLUSIVE) + * expcted_type may be GFS_DT_UNKNOWN, and that means "don't care". + * if (op == INODE_CREATE || op == INODE_CREATE_EXCLUSIVE) + * new_mode must be passed, otherwise it's ignored. + * if ((op == INODE_CREATE || op == INODE_CREATE_EXCLUSIVE) && + * expected_type == GFS_DT_LNK) + * symlink_src must be passed, otherwise it's ignored. + */ static gfarm_error_t inode_lookup_basename(struct inode *parent, const char *name, int len, - int is_dir, enum gfarm_inode_lookup_op op, struct user *user, + int expected_type, enum gfarm_inode_lookup_op op, struct user *user, + gfarm_mode_t new_mode, char *symlink_src, struct inode **inp, int *createdp) { gfarm_error_t e; @@ -813,46 +860,46 @@ struct inode *n; if (len == 0) { - if (op == INODE_REMOVE) + if (op != INODE_LOOKUP) return (GFARM_ERR_INVALID_ARGUMENT); *inp = parent; - *createdp = 0; return (GFARM_ERR_NO_ERROR); } else if (len == 1 && name[0] == '.') { - if (op == INODE_REMOVE) + if (op != INODE_LOOKUP) return (GFARM_ERR_INVALID_ARGUMENT); *inp = parent; - *createdp = 0; return (GFARM_ERR_NO_ERROR); - } + } else if (memchr(name, '/', len) != NULL) + return (GFARM_ERR_INVALID_ARGUMENT); if (len > GFS_MAXNAMLEN) len = GFS_MAXNAMLEN; - if (op != INODE_CREATE && op != INODE_LINK) { + if (op != INODE_CREATE && op != INODE_CREATE_EXCLUSIVE && + op != INODE_LINK) { entry = dir_lookup(parent->u.c.s.d.entries, name, len); if (entry == NULL) return (GFARM_ERR_NO_SUCH_FILE_OR_DIRECTORY); - if (op == INODE_REMOVE) { - if ((e = inode_access(parent, user, GFS_W_OK)) != - GFARM_ERR_NO_ERROR) { - return (e); - } + if (op == INODE_LOOKUP) { *inp = dir_entry_get_inode(entry); - *createdp = 0; - (*inp)->i_nlink--; - dir_remove_entry(parent->u.c.s.d.entries, name, len); - inode_modified(parent); - - e = db_direntry_remove(parent->i_number, name, len); - if (e != GFARM_ERR_NO_ERROR) - gflog_error("db_direntry_remove(%" GFARM_PRId64 - ", %.*s): %s", - parent->i_number, len, name, - gfarm_error_string(e)); - return (GFARM_ERR_NO_ERROR); } + + assert(op == INODE_REMOVE); + if ((e = inode_access(parent, user, GFS_W_OK)) != + GFARM_ERR_NO_ERROR) { + return (e); + } *inp = dir_entry_get_inode(entry); - *createdp = 0; + (*inp)->i_nlink--; + dir_remove_entry(parent->u.c.s.d.entries, name, len); + inode_modified(parent); + + e = db_direntry_remove(parent->i_number, name, len); + if (e != GFARM_ERR_NO_ERROR) + gflog_error("db_direntry_remove(%" GFARM_PRId64 + ", %.*s): %s", + parent->i_number, len, name, + gfarm_error_string(e)); + return (GFARM_ERR_NO_ERROR); } @@ -860,6 +907,9 @@ if (entry == NULL) return (GFARM_ERR_NO_MEMORY); if (!created) { + if (op == INODE_CREATE_EXCLUSIVE || op == INODE_LINK) + return (GFARM_ERR_ALREADY_EXISTS); + assert(op == INODE_CREATE); *inp = dir_entry_get_inode(entry); *createdp = 0; return (GFARM_ERR_NO_ERROR); @@ -887,20 +937,27 @@ parent->i_number, n->i_number, gfarm_error_string(e)); - *createdp = 1; return (GFARM_ERR_NO_ERROR); } + assert((op == INODE_CREATE || op == INODE_CREATE_EXCLUSIVE) && + expected_type != GFS_DT_UNKNOWN); n = inode_alloc(); if (n == NULL) { dir_remove_entry(parent->u.c.s.d.entries, name, len); return (GFARM_ERR_NO_MEMORY); } - e = is_dir ? inode_init_dir(n, parent) : inode_init_file(n); + switch (expected_type) { + case GFS_DT_DIR: e = inode_init_dir(n, parent); break; + case GFS_DT_REG: e = inode_init_file(n); break; + case GFS_DT_LNK: e = inode_init_symlink(n, symlink_src); break; + default: assert(0); e = GFARM_ERR_UNKNOWN; break; + } if (e != GFARM_ERR_NO_ERROR) { dir_remove_entry(parent->u.c.s.d.entries, name, len); inode_free(n); return (e); } + n->i_mode |= new_mode; n->i_user = user; n->i_group = parent->i_group; n->i_size = 0; @@ -938,7 +995,7 @@ * due to LDAP DN hierarchy. * See the comment in inode_init_dir() too. */ - if (is_dir) { + if (expected_type == GFS_DT_DIR) { e = db_direntry_add(n->i_number, dot, DOT_LEN, n->i_number); if (e != GFARM_ERR_NO_ERROR) gflog_error("db_direntry_add(%" GFARM_PRId64 @@ -952,6 +1009,13 @@ ", \"..\", %" GFARM_PRId64 "): %s", parent->i_number, n->i_number, gfarm_error_string(e)); + } else if (expected_type == GFS_DT_LNK) { + e = db_symlink_add(n->i_number, symlink_src); + if (e != GFARM_ERR_NO_ERROR) + gflog_error("db_symlink_add(%" GFARM_PRId64 + ", \"%s\"): %s", + n->i_number, symlink_src, + gfarm_error_string(e)); } e = db_direntry_add(parent->i_number, name, len, n->i_number); if (e != GFARM_ERR_NO_ERROR) @@ -961,17 +1025,30 @@ gfarm_error_string(e)); *inp = n; - *createdp = 1; + if (op == INODE_CREATE) + *createdp = 1; return (GFARM_ERR_NO_ERROR); } /* XXX TODO: namei cache */ -/* if (op == INODE_LINK) *inp is an input parameter instead of output */ -/* if (op != INODE_CREATE), (is_dir) may be -1, and that means "don't care". */ +/* + * if (op == INODE_LINK) + * (*inp) is an input parameter instead of output. + * if (op == INODE_CREATE) + * createdp must be passed, otherwise it's ignored. + * if (op != INODE_CREATE && op != INODE_CREATE_EXCLUSIVE) + * expcted_type may be GFS_DT_UNKNOWN, and that means "don't care". + * if (op == INODE_CREATE || op == INODE_CREATE_EXCLUSIVE) + * new_mode must be passed, otherwise it's ignored. + * if ((op == INODE_CREATE || op == INODE_CREATE_EXCLUSIVE) && + * expected_type == GFS_DT_LNK) + * symlink_src must be passed, otherwise it's ignored. + */ gfarm_error_t inode_lookup_relative(struct inode *n, char *name, - int is_dir, enum gfarm_inode_lookup_op op, - struct user *user, struct inode **inp, int *createdp) + int expected_type, enum gfarm_inode_lookup_op op, struct user *user, + gfarm_mode_t new_mode, char *symlink_src, + struct inode **inp, int *createdp) { gfarm_error_t e; int len = strlen(name); @@ -987,13 +1064,18 @@ if (op == INODE_LINK) nn = *inp; e = inode_lookup_basename(n, name, len, - is_dir, op, user, &nn, createdp); + expected_type, op, user, new_mode, symlink_src, &nn, createdp); if (e != GFARM_ERR_NO_ERROR) return (e); - if (is_dir != -1 && inode_is_dir(nn) != is_dir) - return (is_dir ? - GFARM_ERR_NOT_A_DIRECTORY : - GFARM_ERR_IS_A_DIRECTORY); + if (expected_type != GFS_DT_UNKNOWN && + gfs_mode_to_type(nn->i_mode) != expected_type) { + assert(op != INODE_CREATE_EXCLUSIVE && + (op != INODE_CREATE || !*createdp)); + return ( + expected_type == GFS_DT_DIR ? GFARM_ERR_NOT_A_DIRECTORY : + GFARM_S_ISDIR(nn->i_mode) ? GFARM_ERR_IS_A_DIRECTORY : + GFARM_ERR_OPERATION_NOT_SUPPORTED); + } *inp = nn; return (GFARM_ERR_NO_ERROR); } @@ -1017,10 +1099,9 @@ struct inode **inp) { struct inode *inode; - int created; struct user *user = process_get_user(process); - gfarm_error_t e = inode_lookup_relative(base, dotdot, 1, - INODE_LOOKUP, user, &inode, &created); + gfarm_error_t e = inode_lookup_relative(base, dotdot, GFS_DT_DIR, + INODE_LOOKUP, user, 0, NULL, &inode, NULL); if (e == GFARM_ERR_NO_ERROR && (e = inode_access(inode, user, op)) == GFARM_ERR_NO_ERROR) { @@ -1035,10 +1116,9 @@ struct inode **inp) { struct inode *inode; - int created; struct user *user = process_get_user(process); - gfarm_error_t e = inode_lookup_relative(base, name, -1, - INODE_LOOKUP, user, &inode, &created); + gfarm_error_t e = inode_lookup_relative(base, name, GFS_DT_UNKNOWN, + INODE_LOOKUP, user, 0, NULL, &inode, NULL); if (e == GFARM_ERR_NO_ERROR) { if ((op & GFS_W_OK) != 0 && inode_is_dir(inode)) { @@ -1061,29 +1141,12 @@ struct inode *inode; int created; struct user *user = process_get_user(process); - gfarm_error_t e = inode_lookup_relative(base, name, 0, - INODE_CREATE, user, &inode, &created); + gfarm_error_t e = inode_lookup_relative(base, name, GFS_DT_REG, + INODE_CREATE, user, mode, NULL, &inode, &created); if (e == GFARM_ERR_NO_ERROR) { - if (created) { - inode->i_mode |= mode; - /* - * XXX FIXME - * This is just after db_inode_add/modify(), and - * it's wastful to write the mode to the DB again. - */ - e = db_inode_mode_modify(inode->i_number, - inode->i_mode); - if (e != GFARM_ERR_NO_ERROR) - gflog_error("db_inode_mode_modify(%" - GFARM_PRId64 "): %s", - inode->i_number, - gfarm_error_string(e)); - } else if ((op & GFS_W_OK) != 0 && inode_is_dir(inode)) { - e = GFARM_ERR_IS_A_DIRECTORY; - } else { + if (!created) e = inode_access(inode, user, op); - } if (e == GFARM_ERR_NO_ERROR) { *inp = inode; *createdp = created; @@ -1097,46 +1160,29 @@ struct process *process, gfarm_mode_t mode) { struct inode *inode; - int created; - struct user *user = process_get_user(process); - gfarm_error_t e = inode_lookup_relative(base, name, 1, - INODE_CREATE, user, &inode, &created); - if (e == GFARM_ERR_NO_ERROR) { - if (created) { - inode->i_mode |= mode; - /* - * XXX FIXME - * This is just after db_inode_add/modify(), and - * it's wastful to write the mode to the DB again. - */ - e = db_inode_mode_modify(inode->i_number, - inode->i_mode); - if (e != GFARM_ERR_NO_ERROR) - gflog_error("db_inode_mode_modify(%" - GFARM_PRId64 "): %s", - inode->i_number, gfarm_error_string(e)); - } else { - e = GFARM_ERR_ALREADY_EXISTS; - } - } - return (e); + return (inode_lookup_relative(base, name, GFS_DT_DIR, + INODE_CREATE_EXCLUSIVE, process_get_user(process), mode, NULL, + ... [truncated message content] |