server: Add directories to recursive watches as they're opened.
This commit is contained in:
parent
3faa942c8f
commit
4212108598
106
server/change.c
106
server/change.c
|
@ -934,6 +934,105 @@ static int inotify_adjust_changes( struct dir *dir )
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *get_basename( const char *link )
|
||||||
|
{
|
||||||
|
char *buffer, *name = NULL;
|
||||||
|
int r, n = 0x100;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
buffer = malloc( n );
|
||||||
|
if (!buffer) break;
|
||||||
|
|
||||||
|
r = readlink( link, buffer, n );
|
||||||
|
if (r < 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (r < n)
|
||||||
|
{
|
||||||
|
name = buffer;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
free( buffer );
|
||||||
|
n *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name)
|
||||||
|
{
|
||||||
|
while (r > 0 && name[ r - 1 ] == '/' )
|
||||||
|
r--;
|
||||||
|
name[ r ] = 0;
|
||||||
|
|
||||||
|
name = strrchr( name, '/' );
|
||||||
|
if (name)
|
||||||
|
name = strdup( &name[1] );
|
||||||
|
}
|
||||||
|
|
||||||
|
free( buffer );
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (!inotify_fd)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
unix_fd = get_unix_fd( dir->fd );
|
||||||
|
|
||||||
|
/* check if it's in the list of inodes we want to watch */
|
||||||
|
if (-1 == fstat( unix_fd, &st_new ))
|
||||||
|
return 0;
|
||||||
|
inode = find_inode( st_new.st_dev, st_new.st_ino );
|
||||||
|
if (inode)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* lookup the parent */
|
||||||
|
sprintf( link, "/proc/self/fd/%u/..", unix_fd );
|
||||||
|
if (-1 == stat( link, &st ))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If there's no parent, stop. We could keep going adding
|
||||||
|
* ../ to the path until we hit the root of the tree or
|
||||||
|
* find a recursively watched ancestor.
|
||||||
|
* Assume it's too expensive to search up the tree for now.
|
||||||
|
*/
|
||||||
|
parent = find_inode( st.st_dev, st.st_ino );
|
||||||
|
if (!parent)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (parent->wd == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
filter = filter_from_inode( parent, 1 );
|
||||||
|
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 );
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
static int init_inotify( void )
|
static int init_inotify( void )
|
||||||
|
@ -951,6 +1050,11 @@ static void free_inode( struct inode *inode )
|
||||||
assert( 0 );
|
assert( 0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dir_add_to_existing_notify( struct dir *dir )
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* USE_INOTIFY */
|
#endif /* USE_INOTIFY */
|
||||||
|
|
||||||
struct object *create_dir_obj( struct fd *fd )
|
struct object *create_dir_obj( struct fd *fd )
|
||||||
|
@ -973,6 +1077,8 @@ struct object *create_dir_obj( struct fd *fd )
|
||||||
dir->fd = fd;
|
dir->fd = fd;
|
||||||
set_fd_user( fd, &dir_fd_ops, &dir->obj );
|
set_fd_user( fd, &dir_fd_ops, &dir->obj );
|
||||||
|
|
||||||
|
dir_add_to_existing_notify( dir );
|
||||||
|
|
||||||
return &dir->obj;
|
return &dir->obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue