From: Damjan Jovanovic Subject: [PATCH 7/7] server: use internal paths instead of /proc lookups for inotify Message-Id: Date: Sun, 31 Oct 2021 17:50:37 +0200 The inotify code uses the /proc/self/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 --- server/change.c | 88 ++++++++++++++++++++++++------------------------- 1 file changed, 43 insertions(+), 45 deletions(-) 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