|
@@ -25,12 +25,15 @@
|
|
|
#include <shim_handle.h>
|
|
|
#include <shim_fs.h>
|
|
|
#include <shim_profile.h>
|
|
|
+#include <shim_thread.h>
|
|
|
|
|
|
#include <pal.h>
|
|
|
#include <pal_error.h>
|
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
+#include <linux/fcntl.h>
|
|
|
+
|
|
|
int shim_do_stat (const char * file, struct stat * stat)
|
|
|
{
|
|
|
if (!file || test_user_string(file))
|
|
@@ -195,3 +198,57 @@ int shim_do_fstatfs (int fd, struct statfs * buf)
|
|
|
put_handle(hdl);
|
|
|
return __do_statfs (fs, buf);
|
|
|
}
|
|
|
+
|
|
|
+int shim_do_newfstatat(int dirfd, const char* pathname,
|
|
|
+ struct stat* statbuf, int flags)
|
|
|
+{
|
|
|
+ if (flags & ~(AT_EMPTY_PATH | AT_NO_AUTOMOUNT | AT_SYMLINK_NOFOLLOW))
|
|
|
+ return -EINVAL;
|
|
|
+ if (test_user_string(pathname))
|
|
|
+ return -EFAULT;
|
|
|
+ if (test_user_memory(statbuf, sizeof(*statbuf), true))
|
|
|
+ return -EFAULT;
|
|
|
+
|
|
|
+ int lookup_flags = LOOKUP_ACCESS | LOOKUP_FOLLOW;
|
|
|
+ if (flags & AT_SYMLINK_NOFOLLOW)
|
|
|
+ lookup_flags &= ~LOOKUP_FOLLOW;
|
|
|
+ if (flags & AT_NO_AUTOMOUNT) {
|
|
|
+ /* Do nothing as automount isn't supported */
|
|
|
+ debug("ignoring AT_NO_AUTOMOUNT.");
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!*pathname){
|
|
|
+ if (!(flags & AT_EMPTY_PATH))
|
|
|
+ return -ENOENT;
|
|
|
+
|
|
|
+ if (dirfd == AT_FDCWD) {
|
|
|
+ struct shim_dentry * cwd = get_cur_thread()->cwd;
|
|
|
+ struct shim_d_ops* d_ops = cwd->fs->d_ops;
|
|
|
+ if (d_ops && d_ops->stat)
|
|
|
+ return d_ops->stat(cwd, statbuf);
|
|
|
+ return -EACCES;
|
|
|
+ }
|
|
|
+ return shim_do_fstat(dirfd, statbuf);
|
|
|
+ }
|
|
|
+
|
|
|
+ struct shim_dentry* dir = NULL;
|
|
|
+ if (*pathname != '/') {
|
|
|
+ int ret = path_startat(dirfd, &dir);
|
|
|
+ if (ret < 0)
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ struct shim_dentry* dent;
|
|
|
+ int ret = path_lookupat(dir, pathname, lookup_flags, &dent, NULL);
|
|
|
+ if (ret >= 0) {
|
|
|
+ struct shim_d_ops* d_ops = dent->fs->d_ops;
|
|
|
+ if (d_ops && d_ops->stat)
|
|
|
+ ret = d_ops->stat(dent, statbuf);
|
|
|
+ else
|
|
|
+ ret = -EACCES;
|
|
|
+ put_dentry(dent);
|
|
|
+ }
|
|
|
+ if (dir)
|
|
|
+ put_dentry(dir);
|
|
|
+ return ret;
|
|
|
+}
|