/* Make a directory designated by VNODE, like Unix `mkdir'. */
int (*mkdir) (struct android_vnode *, mode_t);
+ /* Change the access mode of the provided VNODE to MODE. Value is
+ the same as with `chmod'. FLAGS is passed verbatim from the call
+ to the delegating at-func, and is probably
+ AT_SYMLINK_NOFOLLOW. */
+ int (*chmod) (struct android_vnode *, mode_t, int);
+
/* Open the specified VNODE as a directory.
Value is a ``directory handle'', or NULL upon failure. */
struct android_vdir *(*opendir) (struct android_vnode *);
static int android_unix_stat (struct android_vnode *, struct stat *);
static int android_unix_access (struct android_vnode *, int);
static int android_unix_mkdir (struct android_vnode *, mode_t);
+static int android_unix_chmod (struct android_vnode *, mode_t, int);
static struct android_vdir *android_unix_opendir (struct android_vnode *);
/* Vector of VFS operations associated with Unix filesystem VFS
android_unix_stat,
android_unix_access,
android_unix_mkdir,
+ android_unix_chmod,
android_unix_opendir,
};
return mkdir (vp->name, mode);
}
+static int
+android_unix_chmod (struct android_vnode *vnode, mode_t mode,
+ int flags)
+{
+ struct android_unix_vnode *vp;
+
+ vp = (struct android_unix_vnode *) vnode;
+ return fchmodat (AT_FDCWD, vp->name, mode, flags);
+}
+
static struct dirent *
android_unix_readdir (struct android_vdir *vdir)
{
static int android_afs_stat (struct android_vnode *, struct stat *);
static int android_afs_access (struct android_vnode *, int);
static int android_afs_mkdir (struct android_vnode *, mode_t);
+static int android_afs_chmod (struct android_vnode *, mode_t, int);
static struct android_vdir *android_afs_opendir (struct android_vnode *);
/* Vector of VFS operations associated with asset VFS nodes. */
android_afs_stat,
android_afs_access,
android_afs_mkdir,
+ android_afs_chmod,
android_afs_opendir,
};
return -1;
}
+static int
+android_afs_chmod (struct android_vnode *vnode, mode_t mode,
+ int flags)
+{
+ errno = EROFS;
+ return -1;
+}
+
static struct dirent *
android_afs_readdir (struct android_vdir *vdir)
{
static int android_content_stat (struct android_vnode *, struct stat *);
static int android_content_access (struct android_vnode *, int);
static int android_content_mkdir (struct android_vnode *, mode_t);
+static int android_content_chmod (struct android_vnode *, mode_t, int);
static struct android_vdir *android_content_opendir (struct android_vnode *);
/* Vector of VFS operations associated with the content VFS node. */
android_content_stat,
android_content_access,
android_content_mkdir,
+ android_content_chmod,
android_content_opendir,
};
return 0;
}
+static int
+android_content_chmod (struct android_vnode *vnode, mode_t mode,
+ int flags)
+{
+ errno = EACCES;
+ return 0;
+}
+
static struct dirent *
android_content_readdir (struct android_vdir *vdir)
{
static int android_authority_stat (struct android_vnode *, struct stat *);
static int android_authority_access (struct android_vnode *, int);
static int android_authority_mkdir (struct android_vnode *, mode_t);
+static int android_authority_chmod (struct android_vnode *, mode_t, int);
static struct android_vdir *android_authority_opendir (struct android_vnode *);
/* Vector of VFS operations associated with the content VFS node. */
android_authority_stat,
android_authority_access,
android_authority_mkdir,
+ android_authority_chmod,
android_authority_opendir,
};
return -1;
}
+static int
+android_authority_chmod (struct android_vnode *vnode, mode_t mode,
+ int flags)
+{
+ errno = EACCES;
+ return -1;
+}
+
static struct android_vdir *
android_authority_opendir (struct android_vnode *vnode)
{
static int android_saf_root_stat (struct android_vnode *, struct stat *);
static int android_saf_root_access (struct android_vnode *, int);
static int android_saf_root_mkdir (struct android_vnode *, mode_t);
+static int android_saf_root_chmod (struct android_vnode *, mode_t, int);
static struct android_vdir *android_saf_root_opendir (struct android_vnode *);
/* Vector of VFS operations associated with the SAF root VFS node. */
android_saf_root_stat,
android_saf_root_access,
android_saf_root_mkdir,
+ android_saf_root_chmod,
android_saf_root_opendir,
};
return -1;
}
+static int
+android_saf_root_chmod (struct android_vnode *vnode, mode_t mode,
+ int flags)
+{
+ errno = EACCES;
+ return -1;
+}
+
static struct dirent *
android_saf_root_readdir (struct android_vdir *vdir)
{
static int android_saf_tree_stat (struct android_vnode *, struct stat *);
static int android_saf_tree_access (struct android_vnode *, int);
static int android_saf_tree_mkdir (struct android_vnode *, mode_t);
+static int android_saf_tree_chmod (struct android_vnode *, mode_t, int);
static struct android_vdir *android_saf_tree_opendir (struct android_vnode *);
/* Vector of VFS operations associated with SAF tree VFS nodes. */
android_saf_tree_stat,
android_saf_tree_access,
android_saf_tree_mkdir,
+ android_saf_tree_chmod,
android_saf_tree_opendir,
};
return -1;
}
+static int
+android_saf_tree_chmod (struct android_vnode *vnode, mode_t mode,
+ int flags)
+{
+ /* Return EACCESS should MODE contain unusual bits besides S_IFDIR |
+ S_IRUSR | S_IXUSR. */
+
+ if (mode & ~(S_IFDIR | S_IRUSR | S_IXUSR))
+ {
+ errno = EACCES;
+ return -1;
+ }
+
+ /* Otherwise, no further action is necessary, as SAF nodes already
+ pretend to be S_IFDIR | S_IRUSR | S_IXUSR. */
+ return 0;
+}
+
/* Open a database Cursor containing each directory entry within the
supplied SAF tree vnode VP.
android_saf_tree_stat,
android_saf_tree_access,
android_saf_tree_mkdir,
+ android_saf_tree_chmod,
android_saf_file_opendir,
};
static int android_saf_new_stat (struct android_vnode *, struct stat *);
static int android_saf_new_access (struct android_vnode *, int);
static int android_saf_new_mkdir (struct android_vnode *, mode_t);
+static int android_saf_new_chmod (struct android_vnode *, mode_t, int);
static struct android_vdir *android_saf_new_opendir (struct android_vnode *);
/* Vector of VFS operations associated with SAF new VFS nodes. */
android_saf_new_stat,
android_saf_new_access,
android_saf_new_mkdir,
+ android_saf_new_chmod,
android_saf_new_opendir,
};
return 0;
}
+static int
+android_saf_new_chmod (struct android_vnode *vnode, mode_t mode,
+ int flags)
+{
+ errno = ENOENT;
+ return -1;
+}
+
static struct android_vdir *
android_saf_new_opendir (struct android_vnode *vnode)
{
android_unix_stat,
android_unix_access,
android_unix_mkdir,
+ android_unix_chmod,
android_unix_opendir,
};
return rc;
}
+/* Like `android_fstatat', but set file modes instead of
+ checking file status and respect FLAGS. */
+
+int
+android_fchmodat (int dirfd, const char *pathname, mode_t mode,
+ int flags)
+{
+ char buffer[PATH_MAX + 1];
+ struct android_vnode *vp;
+ int rc;
+
+ if (dirfd == AT_FDCWD || pathname[0] == '/')
+ goto vfs;
+
+ /* Now establish whether DIRFD is a file descriptor corresponding to
+ an open VFS directory stream. */
+
+ if (!android_fstatat_1 (dirfd, pathname, buffer, PATH_MAX + 1))
+ {
+ pathname = buffer;
+ goto vfs;
+ }
+
+ /* Fall back to fchmodat. */
+ return fchmodat (dirfd, pathname, mode, flags);
+
+ vfs:
+ vp = android_name_file (pathname);
+ if (!vp)
+ return -1;
+
+ rc = (*vp->ops->chmod) (vp, mode, flags);
+ (*vp->ops->close) (vp);
+ return rc;
+}
+
/* Like `fdopen', but if FD is a parcel file descriptor, ``detach'' it
from the original.