[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