[PATCH 7/7] server: use internal paths instead of /proc lookups for inotify

Damjan Jovanovic damjan.jov at gmail.com
Sun Oct 31 10:50:37 CDT 2021


The inotify code uses the /proc/self/fd/<FD> symlinks to translate
file descriptors to filesystem paths. This is Linux-specific and
unnecessary, as we already store the paths internally, in our
'struct fd'. Use those instead, which gets the file change
notifications to also work on FreeBSD.

Signed-off-by: Damjan Jovanovic <damjan.jov at gmail.com>
---
 server/change.c | 88 ++++++++++++++++++++++++-------------------------
 1 file changed, 43 insertions(+), 45 deletions(-)
-------------- next part --------------
diff --git a/server/change.c b/server/change.c
index 4fdb0394922..d6adc6f7173 100644
--- a/server/change.c
+++ b/server/change.c
@@ -735,10 +735,8 @@ static char *inode_get_path( struct inode *inode, int sz )
     head = list_head( &inode->dirs );
     if (head)
     {
-        int unix_fd = get_unix_fd( LIST_ENTRY( head, struct dir, in_entry )->fd );
-        path = malloc ( 32 + sz );
-        if (path)
-            sprintf( path, "/proc/self/fd/%u/", unix_fd );
+        struct dir *dir = LIST_ENTRY( head, struct dir, in_entry );
+        path = dup_fd_name( dir->fd, "" );
         return path;
     }
 
@@ -966,8 +964,8 @@ static int inotify_adjust_changes( struct dir *dir )
     unsigned int filter;
     struct inode *inode;
     struct stat st;
-    char path[32];
     int wd, unix_fd;
+    char *dir_path;
 
     if (!inotify_fd)
         return 0;
@@ -992,8 +990,11 @@ static int inotify_adjust_changes( struct dir *dir )
 
     filter = filter_from_inode( inode, 0 );
 
-    sprintf( path, "/proc/self/fd/%u", unix_fd );
-    wd = inotify_add_dir( path, filter );
+    wd = -1;
+    dir_path = dup_fd_name( dir->fd, "" );
+    if (dir_path)
+        wd = inotify_add_dir( dir_path, filter );
+    free( dir_path );
     if (wd == -1) return 0;
 
     inode_set_wd( inode, wd );
@@ -1004,25 +1005,12 @@ static int inotify_adjust_changes( struct dir *dir )
 static char *get_basename( const char *link )
 {
     char *buffer, *name = NULL;
-    int r, n = 0x100;
-
-    while (1)
-    {
-        buffer = malloc( n );
-        if (!buffer) return NULL;
-
-        r = readlink( link, buffer, n );
-        if (r < 0)
-            break;
+    int r;
 
-        if (r < n)
-        {
-            name = buffer;
-            break;
-        }
-        free( buffer );
-        n *= 2;
-    }
+    buffer = realpath( link, NULL );
+    if (buffer == NULL)
+        return NULL;
+    name = buffer;
 
     if (name)
     {
@@ -1044,8 +1032,8 @@ static int dir_add_to_existing_notify( struct dir *dir )
     struct inode *inode, *parent;
     unsigned int filter = 0;
     struct stat st, st_new;
-    char link[35], *name;
-    int wd, unix_fd;
+    char *path, *name;
+    int wd, unix_fd, ret;
 
     if (!inotify_fd)
         return 0;
@@ -1060,8 +1048,12 @@ static int dir_add_to_existing_notify( struct dir *dir )
         return 0;
 
     /* lookup the parent */
-    sprintf( link, "/proc/self/fd/%u/..", unix_fd );
-    if (-1 == stat( link, &st ))
+    path = dup_fd_name( dir->fd, ".." );
+    if (!path)
+        return 0;
+    ret = stat( path, &st );
+    free( path );
+    if (-1 == ret)
         return 0;
 
     /*
@@ -1081,23 +1073,29 @@ static int dir_add_to_existing_notify( struct dir *dir )
     if (!filter)
         return 0;
 
-    sprintf( link, "/proc/self/fd/%u", unix_fd );
-    name = get_basename( link );
-    if (!name)
-        return 0;
-    inode = inode_add( parent, st_new.st_dev, st_new.st_ino, name );
-    free( name );
-    if (!inode)
-        return 0;
-
-    /* Couldn't find this inode at the start of the function, must be new */
-    assert( inode->wd == -1 );
-
-    wd = inotify_add_dir( link, filter );
-    if (wd != -1)
-        inode_set_wd( inode, wd );
+    ret = 0;
+    path = dup_fd_name( dir->fd, "" );
+    if (path)
+    {
+        name = get_basename( path );
+        if (name)
+        {
+            inode = inode_add( parent, st_new.st_dev, st_new.st_ino, name );
+            if (inode)
+            {
+                /* Couldn't find this inode at the start of the function, must be new */
+                assert( inode->wd == -1 );
 
-    return 1;
+                wd = inotify_add_dir( path, filter );
+                if (wd != -1)
+                    inode_set_wd( inode, wd );
+                ret = 1;
+            }
+            free( name );
+        }
+        free( path );
+    }
+    return ret;
 }
 
 #else


More information about the wine-devel mailing list