Blob Blame History Raw
From 2159055ede95b410efe7a0925a499df1d8ee23b2 Mon Sep 17 00:00:00 2001
From: Giuseppe Scrivano <gscrivan@redhat.com>
Date: Fri, 31 Jan 2020 13:46:07 +0100
Subject: [PATCH] main: lookup skip ino if there is no origin

if there is no origin xattr specified, do not overwrite the ino
number.

Closes: https://github.com/containers/fuse-overlayfs/issues/177

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
---
 main.c | 48 ++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 38 insertions(+), 10 deletions(-)

diff --git a/main.c b/main.c
index b1bdfa4..ba12faa 100644
--- a/main.c
+++ b/main.c
@@ -1,7 +1,7 @@
 /* fuse-overlayfs: Overlay Filesystem in Userspace
 
    Copyright (C) 2018 Giuseppe Scrivano <giuseppe@scrivano.org>
-   Copyright (C) 2018-2019 Red Hat Inc.
+   Copyright (C) 2018-2020 Red Hat Inc.
    Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
 
    This program is free software: you can redistribute it and/or modify
@@ -456,6 +456,22 @@ has_prefix (const char *str, const char *pref)
   return false;
 }
 
+static int
+set_fd_origin (int fd, const char *origin)
+{
+  cleanup_close int opq_whiteout_fd = -1;
+  size_t len = strlen (origin) + 1;
+  int ret;
+
+  ret = fsetxattr (fd, ORIGIN_XATTR, origin, len, 0);
+  if (ret < 0)
+    {
+      if (errno == ENOTSUP)
+        return 0;
+    }
+  return ret;
+}
+
 static int
 set_fd_opaque (int fd)
 {
@@ -1131,6 +1147,7 @@ make_ovl_node (struct ovl_data *lo, const char *path, struct ovl_layer *layer, c
   mode_t mode = 0;
   char *new_name;
   struct ovl_node *ret_xchg;
+  bool has_origin = true;
   cleanup_node_init struct ovl_node *ret = NULL;
 
   ret = calloc (1, sizeof (*ret));
@@ -1211,10 +1228,13 @@ make_ovl_node (struct ovl_data *lo, const char *path, struct ovl_layer *layer, c
             {
               if (it->ds->statat (it, npath, &st, AT_SYMLINK_NOFOLLOW, STATX_TYPE|STATX_MODE|STATX_INO) == 0)
                 {
-                  ret->tmp_ino = st.st_ino;
-                  ret->tmp_dev = st.st_dev;
-                  if (mode == 0)
-                    mode = st.st_mode;
+                  if (has_origin)
+                    {
+                      ret->tmp_ino = st.st_ino;
+                      ret->tmp_dev = st.st_dev;
+                      if (mode == 0)
+                        mode = st.st_mode;
+                    }
                   ret->last_layer = it;
                 }
                 goto no_fd;
@@ -1223,10 +1243,13 @@ make_ovl_node (struct ovl_data *lo, const char *path, struct ovl_layer *layer, c
           /* It is an open FD, stat the file and read the origin xattrs.  */
           if (it->ds->fstat (it, fd, npath, STATX_TYPE|STATX_MODE|STATX_INO, &st) == 0)
             {
-              ret->tmp_ino = st.st_ino;
-              ret->tmp_dev = st.st_dev;
-              if (mode == 0)
-                mode = st.st_mode;
+              if (has_origin)
+                {
+                  ret->tmp_ino = st.st_ino;
+                  ret->tmp_dev = st.st_dev;
+                  if (mode == 0)
+                    mode = st.st_mode;
+                }
               ret->last_layer = it;
             }
 
@@ -1270,7 +1293,9 @@ make_ovl_node (struct ovl_data *lo, const char *path, struct ovl_layer *layer, c
 
           /* If an origin is specified, use it for the next layer lookup.  */
           s = safe_read_xattr (&origin, fd, ORIGIN_XATTR, PATH_MAX);
-          if (s > 0)
+          if (s <= 0)
+            has_origin = false;
+          else
             {
               free (npath);
               npath = origin;
@@ -2656,6 +2681,9 @@ copyup (struct ovl_data *lo, struct ovl_node *node)
   if (ret < 0)
     goto exit;
 
+  if (set_fd_origin (dfd, node->path) < 0)
+    goto exit;
+
   /* Finally, move the file to its destination.  */
   ret = renameat (lo->workdir_fd, wd_tmp_file_name, get_upper_layer (lo)->fd, node->path);
   if (ret < 0)
-- 
2.24.1