|
@@ -212,9 +212,14 @@ static int create_data (struct shim_dentry * dent, const char * uri, int len)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static int __query_attr (struct shim_file_data * data, PAL_HANDLE pal_handle)
|
|
|
+static int chroot_readdir (struct shim_dentry * dent,
|
|
|
+ struct shim_dirent ** dirent);
|
|
|
+
|
|
|
+static int __query_attr (struct shim_dentry * dent,
|
|
|
+ struct shim_file_data * data, PAL_HANDLE pal_handle)
|
|
|
{
|
|
|
PAL_STREAM_ATTR pal_attr;
|
|
|
+ enum shim_file_type old_type = data->type;
|
|
|
|
|
|
if (pal_handle ?
|
|
|
!DkStreamAttributesQuerybyHandle(pal_handle, &pal_attr) :
|
|
@@ -234,6 +239,42 @@ static int __query_attr (struct shim_file_data * data, PAL_HANDLE pal_handle)
|
|
|
(pal_attr.runnable ? S_IXUSR : 0);
|
|
|
|
|
|
atomic_set(&data->size, pal_attr.pending_size);
|
|
|
+
|
|
|
+ if (data->type == FILE_DIR) {
|
|
|
+ int ret;
|
|
|
+ /* Move up the uri update; need to convert manifest-level file:
|
|
|
+ * directives to 'dir:' uris */
|
|
|
+ if (old_type != FILE_DIR) {
|
|
|
+ dent->state |= DENTRY_ISDIRECTORY;
|
|
|
+ if ((ret = make_uri(dent)) < 0) {
|
|
|
+ unlock(data->lock);
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /* DEP 3/18/17: If we have a directory, we need to find out how many
|
|
|
+ * children it has by hand. */
|
|
|
+ /* XXX: Keep coherent with rmdir/mkdir/creat, etc */
|
|
|
+ struct shim_dirent *d, *dbuf = NULL;
|
|
|
+ int nlink = 0;
|
|
|
+ int rv = chroot_readdir(dent, &dbuf);
|
|
|
+ if (rv != 0)
|
|
|
+ return rv;
|
|
|
+ if (dbuf) {
|
|
|
+ for (d = dbuf; d; d = d->next)
|
|
|
+ nlink++;
|
|
|
+ free(dbuf);
|
|
|
+ debug("Querying a directory; I count %d links.\n", nlink);
|
|
|
+ } else
|
|
|
+ nlink = 2; // Educated guess...
|
|
|
+ data->nlink = nlink;
|
|
|
+ } else {
|
|
|
+ /* DEP 3/18/17: Right now, we don't support hard links,
|
|
|
+ * so just return 1;
|
|
|
+ */
|
|
|
+ data->nlink = 1;
|
|
|
+ }
|
|
|
+
|
|
|
data->queried = true;
|
|
|
|
|
|
return 0;
|
|
@@ -287,21 +328,11 @@ static int query_dentry (struct shim_dentry * dent, PAL_HANDLE pal_handle,
|
|
|
|
|
|
lock(data->lock);
|
|
|
|
|
|
- enum shim_file_type old_type = data->type;
|
|
|
-
|
|
|
- if (!data->queried && (ret = __query_attr(data, pal_handle)) < 0) {
|
|
|
+ if (!data->queried && (ret = __query_attr(dent, data, pal_handle)) < 0) {
|
|
|
unlock(data->lock);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- if (data->type == FILE_DIR && old_type != FILE_DIR) {
|
|
|
- dent->state |= DENTRY_ISDIRECTORY;
|
|
|
- if ((ret = make_uri(dent)) < 0) {
|
|
|
- unlock(data->lock);
|
|
|
- return ret;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
if (mode)
|
|
|
*mode = data->mode;
|
|
|
|
|
@@ -318,14 +349,23 @@ static int query_dentry (struct shim_dentry * dent, PAL_HANDLE pal_handle,
|
|
|
stat->st_atime = (time_t) data->atime;
|
|
|
stat->st_mtime = (time_t) data->mtime;
|
|
|
stat->st_ctime = (time_t) data->ctime;
|
|
|
+ stat->st_nlink = data->nlink;
|
|
|
|
|
|
+
|
|
|
switch (data->type) {
|
|
|
- case FILE_REGULAR: stat->st_mode |= S_IFREG; break;
|
|
|
- case FILE_DIR: stat->st_mode |= S_IFDIR; break;
|
|
|
+ case FILE_REGULAR:
|
|
|
+ stat->st_mode |= S_IFREG;
|
|
|
+ break;
|
|
|
+ case FILE_DIR:
|
|
|
+ stat->st_mode |= S_IFDIR;
|
|
|
+ break;
|
|
|
case FILE_DEV:
|
|
|
- case FILE_TTY: stat->st_mode |= S_IFCHR; break;
|
|
|
+ case FILE_TTY:
|
|
|
+ stat->st_mode |= S_IFCHR;
|
|
|
+ break;
|
|
|
default: break;
|
|
|
}
|
|
|
+ debug("Stat: Returning link cound %d\n", stat->st_nlink);
|
|
|
}
|
|
|
|
|
|
unlock(data->lock);
|
|
@@ -356,7 +396,8 @@ static int chroot_lookup (struct shim_dentry * dent, bool force)
|
|
|
return query_dentry(dent, NULL, NULL, NULL);
|
|
|
}
|
|
|
|
|
|
-static int __chroot_open (const char * uri, int len, int flags, mode_t mode,
|
|
|
+static int __chroot_open (struct shim_dentry * dent,
|
|
|
+ const char * uri, int len, int flags, mode_t mode,
|
|
|
struct shim_handle * hdl,
|
|
|
struct shim_file_data * data)
|
|
|
{
|
|
@@ -396,7 +437,7 @@ static int __chroot_open (const char * uri, int len, int flags, mode_t mode,
|
|
|
|
|
|
if (!data->queried) {
|
|
|
lock(data->lock);
|
|
|
- ret = __query_attr(data, palhdl);
|
|
|
+ ret = __query_attr(dent, data, palhdl);
|
|
|
unlock(data->lock);
|
|
|
}
|
|
|
|
|
@@ -422,7 +463,7 @@ static int chroot_open (struct shim_handle * hdl, struct shim_dentry * dent,
|
|
|
if ((ret = try_create_data(dent, NULL, 0, &data)) < 0)
|
|
|
return ret;
|
|
|
|
|
|
- if ((ret = __chroot_open(NULL, 0, flags, dent->mode, hdl, data)) < 0)
|
|
|
+ if ((ret = __chroot_open(dent, NULL, 0, flags, dent->mode, hdl, data)) < 0)
|
|
|
return ret;
|
|
|
|
|
|
struct shim_file_handle * file = &hdl->info.file;
|
|
@@ -448,7 +489,7 @@ static int chroot_creat (struct shim_handle * hdl, struct shim_dentry * dir,
|
|
|
if ((ret = try_create_data(dent, NULL, 0, &data)) < 0)
|
|
|
return ret;
|
|
|
|
|
|
- if ((ret = __chroot_open(NULL, 0, flags|O_CREAT|O_EXCL, mode, hdl,
|
|
|
+ if ((ret = __chroot_open(dent, NULL, 0, flags|O_CREAT|O_EXCL, mode, hdl,
|
|
|
data)) < 0)
|
|
|
return ret;
|
|
|
|
|
@@ -467,6 +508,14 @@ static int chroot_creat (struct shim_handle * hdl, struct shim_dentry * dir,
|
|
|
hdl->acc_mode = ACC_MODE(flags & O_ACCMODE);
|
|
|
qstrcopy(&hdl->uri, &data->host_uri);
|
|
|
|
|
|
+ /* Increment the parent's link count */
|
|
|
+ struct shim_file_data *parent_data = FILE_DENTRY_DATA(dir);
|
|
|
+ if (parent_data) {
|
|
|
+ lock(parent_data->lock);
|
|
|
+ if (parent_data->queried)
|
|
|
+ parent_data->nlink++;
|
|
|
+ unlock(parent_data->lock);
|
|
|
+ }
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
@@ -485,7 +534,17 @@ static int chroot_mkdir (struct shim_dentry * dir, struct shim_dentry * dent,
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
- return __chroot_open(NULL, 0, O_CREAT|O_EXCL, mode, NULL, data);
|
|
|
+ ret = __chroot_open(dent, NULL, 0, O_CREAT|O_EXCL, mode, NULL, data);
|
|
|
+
|
|
|
+ /* Increment the parent's link count */
|
|
|
+ struct shim_file_data *parent_data = FILE_DENTRY_DATA(dir);
|
|
|
+ if (parent_data) {
|
|
|
+ lock(parent_data->lock);
|
|
|
+ if (parent_data->queried)
|
|
|
+ parent_data->nlink++;
|
|
|
+ unlock(parent_data->lock);
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
#define NEED_RECREATE(hdl) (!FILE_HANDLE_DATA(hdl))
|
|
@@ -512,7 +571,7 @@ static int chroot_recreate (struct shim_handle * hdl)
|
|
|
qstrsetstr(&data->host_uri, uri, len);
|
|
|
}
|
|
|
|
|
|
- return __chroot_open(uri, len, hdl->flags, 0, hdl, data);
|
|
|
+ return __chroot_open(hdl->dentry, uri, len, hdl->flags, 0, hdl, data);
|
|
|
}
|
|
|
|
|
|
static inline bool check_version (struct shim_handle * hdl)
|
|
@@ -1067,6 +1126,15 @@ static int chroot_unlink (struct shim_dentry * dir, struct shim_dentry * dent)
|
|
|
atomic_inc(&data->version);
|
|
|
atomic_set(&data->size, 0);
|
|
|
|
|
|
+ /* Drop the parent's link count */
|
|
|
+ struct shim_file_data *parent_data = FILE_DENTRY_DATA(dir);
|
|
|
+ if (parent_data) {
|
|
|
+ lock(parent_data->lock);
|
|
|
+ if (parent_data->queried)
|
|
|
+ parent_data->nlink--;
|
|
|
+ unlock(parent_data->lock);
|
|
|
+ }
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|