server: Add directories to recursive watches as they're opened.

This commit is contained in:
Mike McCormack 2006-02-23 00:45:34 +09:00 committed by Alexandre Julliard
parent 3faa942c8f
commit 4212108598
1 changed files with 106 additions and 0 deletions

View File

@ -934,6 +934,105 @@ static int inotify_adjust_changes( struct dir *dir )
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
static int init_inotify( void )
@ -951,6 +1050,11 @@ static void free_inode( struct inode *inode )
assert( 0 );
}
static int dir_add_to_existing_notify( struct dir *dir )
{
return 0;
}
#endif /* USE_INOTIFY */
struct object *create_dir_obj( struct fd *fd )
@ -973,6 +1077,8 @@ struct object *create_dir_obj( struct fd *fd )
dir->fd = fd;
set_fd_user( fd, &dir_fd_ops, &dir->obj );
dir_add_to_existing_notify( dir );
return &dir->obj;
}