containerfs: simplify hide_node

use a hard link so we don't modify the destination file before a
rename(2).

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano 2018-06-30 10:59:27 +02:00
parent f2b97eeea5
commit f131a755fa
No known key found for this signature in database
GPG Key ID: E4730F97F60286ED

53
main.c
View File

@ -245,34 +245,42 @@ get_node_path (struct lo_node *node)
} }
static int static int
hide_node (struct lo_data *lo, struct lo_node *node) hide_node (struct lo_data *lo, struct lo_node *node, bool unlink_src)
{ {
char dest[PATH_MAX]; char dest[PATH_MAX];
char *newpath; char *newpath;
int ret; static unsigned long counter = 1;
node->hidden = 1; node->hidden = 1;
node->parent = NULL; node->parent = NULL;
sprintf (dest, "%s/tmp-XXXXXX", lo->workdir); asprintf (&newpath, "%s/%lu", lo->workdir, counter++);
ret = mkstemp (dest);
if (ret < 0)
return ret;
close (ret);
newpath = strdup (dest);
if (newpath == NULL) if (newpath == NULL)
{ {
unlink (dest); unlink (dest);
return -1; return -1;
} }
/* Might be leftover from a previous run. */
unlink (newpath);
if (unlink_src)
{
if (rename (node->path, newpath) < 0) if (rename (node->path, newpath) < 0)
{ {
free (newpath); free (newpath);
unlink (dest);
return -1; return -1;
} }
}
else
{
if (link (node->path, newpath) < 0)
{
free (newpath);
return -1;
}
}
free (node->path); free (node->path);
node->path = newpath; node->path = newpath;
@ -1733,7 +1741,7 @@ do_rm (fuse_req_t req, fuse_ino_t parent, const char *name, bool dirp)
rm = hash_delete (pnode->children, &key); rm = hash_delete (pnode->children, &key);
if (rm) if (rm)
{ {
hide_node (lo, rm); hide_node (lo, rm, true);
node_free (rm); node_free (rm);
} }
@ -2360,22 +2368,6 @@ lo_flock (fuse_req_t req, fuse_ino_t ino,
fuse_reply_err (req, ret == 0 ? 0 : errno); fuse_reply_err (req, ret == 0 ? 0 : errno);
} }
/* used to recover a failed lo_rename. */
static struct lo_node *
unhide_node (struct lo_node *node, struct lo_node *parent)
{
char b[PATH_MAX];
if (node->path == NULL)
return node;
sprintf (b, "%s/%s", parent->path, node->name);
rename (node->path, b);
free (node->path);
node->path = strdup (b);
return insert_node (parent, node, true);
}
static struct lo_node * static struct lo_node *
get_node_up_rec (struct lo_data *lo, struct lo_node *node) get_node_up_rec (struct lo_data *lo, struct lo_node *node)
{ {
@ -2503,7 +2495,7 @@ lo_rename (fuse_req_t req, fuse_ino_t parent, const char *name,
rm = NULL; rm = NULL;
} }
if (rm && !rm->not_exists && hide_node (lo, rm) < 0) if (rm && !rm->not_exists && hide_node (lo, rm, false) < 0)
goto error; goto error;
} }
} }
@ -2511,9 +2503,6 @@ lo_rename (fuse_req_t req, fuse_ino_t parent, const char *name,
ret = syscall (SYS_renameat2, srcfd, name, destfd, newname, flags); ret = syscall (SYS_renameat2, srcfd, name, destfd, newname, flags);
if (ret < 0) if (ret < 0)
{ {
if (rm)
destpnode = unhide_node (rm, destpnode);
pnode->dirty = destpnode->dirty = 1; pnode->dirty = destpnode->dirty = 1;
goto error; goto error;
} }