WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-tools

Re: [Xen-tools] [PATCH] Xenstore mkdir/write implicitly create directori

To: Rusty Russell <rusty@xxxxxxxxxxxxxxx>
Subject: Re: [Xen-tools] [PATCH] Xenstore mkdir/write implicitly create directories
From: Christian Limpach <Christian.Limpach@xxxxxxxxxxxx>
Date: Tue, 23 Aug 2005 20:52:39 +0100
Cc: Xen Tools <xen-tools@xxxxxxxxxxxxxxxxxxx>
Delivery-date: Tue, 23 Aug 2005 19:50:41 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <1124613561.12154.5.camel@xxxxxxxxxxxxxxxxxxxxx>
List-help: <mailto:xen-tools-request@lists.xensource.com?subject=help>
List-id: Xen control tools developers <xen-tools.lists.xensource.com>
List-post: <mailto:xen-tools@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-tools>, <mailto:xen-tools-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-tools>, <mailto:xen-tools-request@lists.xensource.com?subject=unsubscribe>
References: <1124613561.12154.5.camel@xxxxxxxxxxxxxxxxxxxxx>
Sender: xen-tools-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mutt/1.4.1i
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