[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-tools] [PATCH] Xenstore mkdir/write implicitly create directories
Thanks! On Sun, Aug 21, 2005 at 06:39:21PM +1000, Rusty Russell wrote: > Hi Anthony, > > You asked for this a while ago. This changes the xenstore so that > mkdir and write implicitly create subdirs. > > Signed-off-by: Rusty Russell <rusty@xxxxxxxxxxxxxxx> > > # HG changeset patch > # User Rusty Russell <rusty@xxxxxxxxxxxxxxx> > # Node ID 7522ea52b829e2d18cea672da9851f8e7ef6f269 > # Parent 07b986fec159c8bd18f7f109ca78c5b1250ee07c > Make directories implicitly for mkdir and write. > Change directory code: make then move (safer than delete-if-fail). > > diff -r 07b986fec159 -r 7522ea52b829 tools/xenstore/testsuite/02directory.test > --- a/tools/xenstore/testsuite/02directory.test Sun Aug 21 06:29:47 2005 > +++ b/tools/xenstore/testsuite/02directory.test Sun Aug 21 06:38:22 2005 > @@ -32,3 +32,16 @@ > mkdir /dir > expect mkdir failed: File exists > mkdir /dir/test2 > + > +# Mkdir implicitly creates directories. > +mkdir /dir/1/2/3/4 > +expect test2 > +expect 1 > +dir /dir > +expect 2 > +dir /dir/1 > +expect 3 > +dir /dir/1/2 > +expect 4 > +dir /dir/1/2/3 > +dir /dir/1/2/3/4 > diff -r 07b986fec159 -r 7522ea52b829 tools/xenstore/testsuite/03write.test > --- a/tools/xenstore/testsuite/03write.test Sun Aug 21 06:29:47 2005 > +++ b/tools/xenstore/testsuite/03write.test Sun Aug 21 06:38:22 2005 > @@ -18,3 +18,22 @@ > write /test create contents3 > expect contents3 > read /test > + > +# Write should implicitly create directories > +write /dir/test create contents > +expect test > +dir /dir > +expect contents > +read /dir/test > +write /dir/1/2/3/4 excl contents4 > +expect test > +expect 1 > +dir /dir > +expect 2 > +dir /dir/1 > +expect 3 > +dir /dir/1/2 > +expect 4 > +dir /dir/1/2/3 > +expect contents4 > +read /dir/1/2/3/4 > diff -r 07b986fec159 -r 7522ea52b829 > tools/xenstore/testsuite/06dirpermissions.test > --- a/tools/xenstore/testsuite/06dirpermissions.test Sun Aug 21 06:29:47 2005 > +++ b/tools/xenstore/testsuite/06dirpermissions.test Sun Aug 21 06:38:22 2005 > @@ -117,3 +117,11 @@ > write /dir/subdir/subfile excl contents > expect 3 READ/WRITE > getperm /dir/subdir/subfile > + > +# Inheritence works through multiple directories, too. > +write /dir/subdir/1/2/3/4 excl contents > +expect 3 READ/WRITE > +getperm /dir/subdir/1/2/3/4 > +mkdir /dir/subdir/a/b/c/d > +expect 3 READ/WRITE > +getperm /dir/subdir/a/b/c/d > diff -r 07b986fec159 -r 7522ea52b829 tools/xenstore/xenstored_core.c > --- a/tools/xenstore/xenstored_core.c Sun Aug 21 06:29:47 2005 > +++ b/tools/xenstore/xenstored_core.c Sun Aug 21 06:38:22 2005 > @@ -423,14 +423,24 @@ > return node_dir_inside_transaction(trans, node); > } > > +static char *datafile(const char *dir) > +{ > + return talloc_asprintf(dir, "%s/.data", dir); > +} > + > static char *node_datafile(struct transaction *trans, const char *node) > { > - return talloc_asprintf(node, "%s/.data", node_dir(trans, node)); > + return datafile(node_dir(trans, node)); > +} > + > +static char *permfile(const char *dir) > +{ > + return talloc_asprintf(dir, "%s/.perms", dir); > } > > static char *node_permfile(struct transaction *trans, const char *node) > { > - return talloc_asprintf(node, "%s/.perms", node_dir(trans, node)); > + return permfile(node_dir(trans, node)); > } > > struct buffered_data *new_buffer(void *ctx) > @@ -557,15 +567,14 @@ > } > > /* If it fails, returns NULL and sets errno. */ > -static struct xs_permissions *get_perms(struct transaction *transaction, > - const char *node, unsigned int *num) > +static struct xs_permissions *get_perms(const char *dir, unsigned int *num) > { > unsigned int size; > char *strings; > struct xs_permissions *ret; > int *fd; > > - fd = talloc_open(node_permfile(transaction, node), O_RDONLY, 0); > + fd = talloc_open(permfile(dir), O_RDONLY, 0); > if (!fd) > return NULL; > strings = read_all(fd, &size); > @@ -573,14 +582,14 @@ > return NULL; > > *num = xs_count_strings(strings, size); > - ret = talloc_array(node, struct xs_permissions, *num); > + ret = talloc_array(dir, struct xs_permissions, *num); > if (!xs_strings_to_perms(ret, *num, strings)) > - corrupt(NULL, "Permissions corrupt for %s", node); > + corrupt(NULL, "Permissions corrupt for %s", dir); > > return ret; > } > > -static char *perms_to_strings(const char *node, > +static char *perms_to_strings(const void *ctx, > struct xs_permissions *perms, unsigned int num, > unsigned int *len) > { > @@ -592,7 +601,7 @@ > if (!xs_perm_to_string(&perms[i], buffer)) > return NULL; > > - strings = talloc_realloc(node, strings, char, > + strings = talloc_realloc(ctx, strings, char, > *len + strlen(buffer) + 1); > strcpy(strings + *len, buffer); > *len += strlen(buffer) + 1; > @@ -625,16 +634,23 @@ > return 0; > } > > +/* Create a self-destructing temporary path */ > +static char *temppath(const char *path) > +{ > + char *tmppath = talloc_asprintf(path, "%s.tmp", path); > + talloc_set_destructor(tmppath, destroy_path); > + return tmppath; > +} > + > /* Create a self-destructing temporary file */ > static char *tempfile(const char *path, void *contents, unsigned int len) > { > int *fd; > - char *tmppath = talloc_asprintf(path, "%s.tmp", path); > + char *tmppath = temppath(path); > > fd = talloc_open(tmppath, O_WRONLY|O_CREAT|O_EXCL, 0640); > if (!fd) > return NULL; > - talloc_set_destructor(tmppath, destroy_path); > if (!xs_write_all(*fd, contents, len)) > return NULL; > > @@ -732,7 +748,7 @@ > > do { > node = get_parent(node); > - perms = get_perms(conn->transaction, node, &num); > + perms = get_perms(node_dir(conn->transaction, node), &num); > if (perms) > break; > } while (!streq(node, "/")); > @@ -788,7 +804,7 @@ > return false; > } > > - perms = get_perms(conn->transaction, node, &num); > + perms = get_perms(node_dir(conn->transaction, node), &num); > > if (perms) { > if (perm_for_id(conn->id, perms, num) & perm) > @@ -875,44 +891,64 @@ > send_reply(conn, XS_READ, value, size); > } > > -/* Create a new directory. Optionally put data in it (if data != NULL) */ > -static bool new_directory(struct connection *conn, > - const char *node, void *data, unsigned int datalen) > +/* Commit this directory, eg. comitting a/b.tmp/c causes a/b.tmp -> a.b */ > +static bool commit_dir(char *dir) > +{ > + char *dot, *slash, *dest; > + > + dot = strrchr(dir, '.'); > + slash = strchr(dot, '/'); > + if (slash) > + *slash = '\0'; > + > + dest = talloc_asprintf(dir, "%.*s", dot - dir, dir); > + return rename(dir, dest) == 0; > +} > + > +/* Create a temporary directory. Put data in it (if data != NULL) */ > +static char *tempdir(struct connection *conn, > + const char *node, void *data, unsigned int datalen) > { > struct xs_permissions *perms; > char *permstr; > unsigned int num, len; > int *fd; > - char *dir = node_dir(conn->transaction, node); > - > - if (mkdir(dir, 0750) != 0) > - return false; > - > - /* Set destructor so we clean up if neccesary. */ > - talloc_set_destructor(dir, destroy_path); > - > - perms = get_perms(conn->transaction, get_parent(node), &num); > + char *dir; > + > + dir = temppath(node_dir(conn->transaction, node)); > + if (mkdir(dir, 0750) != 0) { > + if (errno != ENOENT) > + return NULL; > + > + dir = tempdir(conn, get_parent(node), NULL, 0); > + if (!dir) > + return NULL; > + > + dir = talloc_asprintf(dir, "%s%s", dir, strrchr(node, '/')); > + if (mkdir(dir, 0750) != 0) > + return NULL; > + talloc_set_destructor(dir, destroy_path); > + } > + > + perms = get_perms(get_parent(dir), &num); > + assert(perms); > /* Domains own what they create. */ > if (conn->id) > perms->id = conn->id; > > permstr = perms_to_strings(dir, perms, num, &len); > - fd = talloc_open(node_permfile(conn->transaction, node), > - O_WRONLY|O_CREAT|O_EXCL, 0640); > + fd = talloc_open(permfile(dir), O_WRONLY|O_CREAT|O_EXCL, 0640); > if (!fd || !xs_write_all(*fd, permstr, len)) > - return false; > + return NULL; > > if (data) { > - char *datapath = node_datafile(conn->transaction, node); > + char *datapath = datafile(dir); > > fd = talloc_open(datapath, O_WRONLY|O_CREAT|O_EXCL, 0640); > if (!fd || !xs_write_all(*fd, data, datalen)) > - return false; > - } > - > - /* Finished! */ > - talloc_set_destructor(dir, NULL); > - return true; > + return NULL; > + } > + return dir; > } > > /* path, flags, data... */ > @@ -959,6 +995,8 @@ > } > > if (lstat(node_dir(conn->transaction, node), &st) != 0) { > + char *dir; > + > /* Does not exist... */ > if (errno != ENOENT) { > send_error(conn, errno); > @@ -971,10 +1009,12 @@ > return; > } > > - if (!new_directory(conn, node, in->buffer + offset, datalen)) { > + dir = tempdir(conn, node, in->buffer + offset, datalen); > + if (!dir || !commit_dir(dir)) { > send_error(conn, errno); > return; > } > + > } else { > /* Exists... */ > if (streq(vec[1], XS_WRITE_CREATE_EXCL)) { > @@ -999,6 +1039,9 @@ > > static void do_mkdir(struct connection *conn, const char *node) > { > + char *dir; > + struct stat st; > + > node = canonicalize(conn, node); > if (!check_node_perms(conn, node, XS_PERM_WRITE|XS_PERM_ENOENT_OK)) { > send_error(conn, errno); > @@ -1013,7 +1056,14 @@ > if (transaction_block(conn, node)) > return; > > - if (!new_directory(conn, node, NULL, 0)) { > + /* Must not already exist. */ > + if (lstat(node_dir(conn->transaction, node), &st) == 0) { > + send_error(conn, EEXIST); > + return; > + } > + > + dir = tempdir(conn, node, NULL, 0); > + if (!dir || !commit_dir(dir)) { > send_error(conn, errno); > return; > } > @@ -1073,7 +1123,7 @@ > return; > } > > - perms = get_perms(conn->transaction, node, &num); > + perms = get_perms(node_dir(conn->transaction, node), &num); > if (!perms) { > send_error(conn, errno); > return; > diff -r 07b986fec159 -r 7522ea52b829 tools/xenstore/xs_random.c > --- a/tools/xenstore/xs_random.c Sun Aug 21 06:29:47 2005 > +++ b/tools/xenstore/xs_random.c Sun Aug 21 06:38:22 2005 > @@ -303,6 +303,34 @@ > return true; > } > > +static char *parent_filename(const char *name) > +{ > + char *slash = strrchr(name + 1, '/'); > + if (!slash) > + return talloc_strdup(name, "/"); > + return talloc_asprintf(name, "%.*s", slash-name, name); > +} > + > +static void make_dirs(const char *filename) > +{ > + struct stat st; > + > + if (lstat(filename, &st) == 0 && S_ISREG(st.st_mode)) > + convert_to_dir(filename); > + > + if (mkdir(filename, 0700) == 0) { > + init_perms(filename); > + return; > + } > + if (errno == EEXIST) > + return; > + > + make_dirs(parent_filename(filename)); > + if (mkdir(filename, 0700) != 0) > + barf_perror("Failed to mkdir %s", filename); > + init_perms(filename); > +} > + > static bool file_write(struct file_ops_info *info, > const char *path, const void *data, > unsigned int len, int createflags) > @@ -329,6 +357,9 @@ > } > } > > + if (createflags & O_CREAT) > + make_dirs(parent_filename(filename)); > + > fd = open(filename, createflags|O_TRUNC|O_WRONLY, 0600); > if (fd < 0) { > /* FIXME: Another hack. */ > @@ -352,6 +383,7 @@ > if (!write_ok(info, path)) > return false; > > + make_dirs(parent_filename(dirname)); > if (mkdir(dirname, 0700) != 0) > return false; > > @@ -420,7 +452,7 @@ > } > > if (abort) { > - cmd = talloc_asprintf(NULL, "rm -r %s", info->transact_base); > + cmd = talloc_asprintf(NULL, "rm -rf %s", info->transact_base); > do_command(cmd); > goto success; > } > @@ -1004,8 +1036,8 @@ > } else { > dup2(fds[1], STDOUT_FILENO); > close(fds[0]); > -#if 0 > - execlp("valgrind", "valgrind", "xenstored_test", "--output-pid", > +#if 1 > + execlp("valgrind", "valgrind", "-q", > "--suppressions=testsuite/vg-suppressions", "xenstored_test", "--output-pid", > "--no-fork", NULL); > #else > execlp("./xenstored_test", "xenstored_test", "--output-pid", > > -- > A bad analogy is like a leaky screwdriver -- Richard Braakman > > > _______________________________________________ > Xen-tools mailing list > Xen-tools@xxxxxxxxxxxxxxxxxxx > http://lists.xensource.com/xen-tools > _______________________________________________ Xen-tools mailing list Xen-tools@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-tools
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |