[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Minios-devel] [UNIKRAFT PATCH v2 05/23] lib/vfscore: tabify imported vfs code
To comply with Unikraft coding style, indents must be tabs, not spaces. Imported code was a mixture of both. Signed-off-by: Yuri Volchkov <yuri.volchkov@xxxxxxxxx> --- lib/vfscore/dentry.c | 268 +-- lib/vfscore/fops.c | 32 +- lib/vfscore/include/vfscore/dentry.h | 4 +- lib/vfscore/include/vfscore/mount.h | 8 +- lib/vfscore/lookup.c | 554 ++--- lib/vfscore/main.c | 2844 +++++++++++++------------- lib/vfscore/mount.c | 580 +++--- lib/vfscore/syscalls.c | 464 ++--- lib/vfscore/task.c | 10 +- lib/vfscore/vfs.h | 2 +- lib/vfscore/vnode.c | 50 +- 11 files changed, 2408 insertions(+), 2408 deletions(-) diff --git a/lib/vfscore/dentry.c b/lib/vfscore/dentry.c index facd9eaa..c2f209b2 100644 --- a/lib/vfscore/dentry.c +++ b/lib/vfscore/dentry.c @@ -55,180 +55,180 @@ static mutex dentry_hash_lock; static u_int dentry_hash(struct mount *mp, const char *path) { - u_int val = 0; - - if (path) { - while (*path) { - val = ((val << 5) + val) + *path++; - } - } - return (val ^ (unsigned long) mp) & (DENTRY_BUCKETS - 1); + u_int val = 0; + + if (path) { + while (*path) { + val = ((val << 5) + val) + *path++; + } + } + return (val ^ (unsigned long) mp) & (DENTRY_BUCKETS - 1); } struct dentry * dentry_alloc(struct dentry *parent_dp, struct vnode *vp, const char *path) { - struct mount *mp = vp->v_mount; - struct dentry *dp = (dentry*)calloc(sizeof(*dp), 1); - - if (!dp) { - return nullptr; - } - - vref(vp); - - dp->d_refcnt = 1; - dp->d_vnode = vp; - dp->d_mount = mp; - dp->d_path = strdup(path); - LIST_INIT(&dp->d_children); - - if (parent_dp) { - dref(parent_dp); - WITH_LOCK(parent_dp->d_lock) { - // Insert dp into its parent's children list. - LIST_INSERT_HEAD(&parent_dp->d_children, dp, d_children_link); - } - } - dp->d_parent = parent_dp; - - vn_add_name(vp, dp); - - mutex_lock(&dentry_hash_lock); - LIST_INSERT_HEAD(&dentry_hash_table[dentry_hash(mp, path)], dp, d_link); - mutex_unlock(&dentry_hash_lock); - return dp; + struct mount *mp = vp->v_mount; + struct dentry *dp = (dentry*)calloc(sizeof(*dp), 1); + + if (!dp) { + return nullptr; + } + + vref(vp); + + dp->d_refcnt = 1; + dp->d_vnode = vp; + dp->d_mount = mp; + dp->d_path = strdup(path); + LIST_INIT(&dp->d_children); + + if (parent_dp) { + dref(parent_dp); + WITH_LOCK(parent_dp->d_lock) { + // Insert dp into its parent's children list. + LIST_INSERT_HEAD(&parent_dp->d_children, dp, d_children_link); + } + } + dp->d_parent = parent_dp; + + vn_add_name(vp, dp); + + mutex_lock(&dentry_hash_lock); + LIST_INSERT_HEAD(&dentry_hash_table[dentry_hash(mp, path)], dp, d_link); + mutex_unlock(&dentry_hash_lock); + return dp; }; struct dentry * dentry_lookup(struct mount *mp, char *path) { - struct dentry *dp; - - mutex_lock(&dentry_hash_lock); - LIST_FOREACH(dp, &dentry_hash_table[dentry_hash(mp, path)], d_link) { - if (dp->d_mount == mp && !strncmp(dp->d_path, path, PATH_MAX)) { - dp->d_refcnt++; - mutex_unlock(&dentry_hash_lock); - return dp; - } - } - mutex_unlock(&dentry_hash_lock); - return nullptr; /* not found */ + struct dentry *dp; + + mutex_lock(&dentry_hash_lock); + LIST_FOREACH(dp, &dentry_hash_table[dentry_hash(mp, path)], d_link) { + if (dp->d_mount == mp && !strncmp(dp->d_path, path, PATH_MAX)) { + dp->d_refcnt++; + mutex_unlock(&dentry_hash_lock); + return dp; + } + } + mutex_unlock(&dentry_hash_lock); + return nullptr; /* not found */ } static void dentry_children_remove(struct dentry *dp) { - struct dentry *entry = nullptr; - - WITH_LOCK(dp->d_lock) { - LIST_FOREACH(entry, &dp->d_children, d_children_link) { - ASSERT(entry); - ASSERT(entry->d_refcnt > 0); - LIST_REMOVE(entry, d_link); - } - } + struct dentry *entry = nullptr; + + WITH_LOCK(dp->d_lock) { + LIST_FOREACH(entry, &dp->d_children, d_children_link) { + ASSERT(entry); + ASSERT(entry->d_refcnt > 0); + LIST_REMOVE(entry, d_link); + } + } } void dentry_move(struct dentry *dp, struct dentry *parent_dp, char *path) { - struct dentry *old_pdp = dp->d_parent; - char *old_path = dp->d_path; - - if (old_pdp) { - WITH_LOCK(old_pdp->d_lock) { - // Remove dp from its old parent's children list. - LIST_REMOVE(dp, d_children_link); - } - } - - if (parent_dp) { - dref(parent_dp); - WITH_LOCK(parent_dp->d_lock) { - // Insert dp into its new parent's children list. - LIST_INSERT_HEAD(&parent_dp->d_children, dp, d_children_link); - } - } - - WITH_LOCK(dentry_hash_lock) { - // Remove all dp's child dentries from the hashtable. - dentry_children_remove(dp); - // Remove dp with outdated hash info from the hashtable. - LIST_REMOVE(dp, d_link); - // Update dp. - dp->d_path = strdup(path); - dp->d_parent = parent_dp; - // Insert dp updated hash info into the hashtable. - LIST_INSERT_HEAD(&dentry_hash_table[dentry_hash(dp->d_mount, path)], - dp, d_link); - } - - if (old_pdp) { - drele(old_pdp); - } - - free(old_path); + struct dentry *old_pdp = dp->d_parent; + char *old_path = dp->d_path; + + if (old_pdp) { + WITH_LOCK(old_pdp->d_lock) { + // Remove dp from its old parent's children list. + LIST_REMOVE(dp, d_children_link); + } + } + + if (parent_dp) { + dref(parent_dp); + WITH_LOCK(parent_dp->d_lock) { + // Insert dp into its new parent's children list. + LIST_INSERT_HEAD(&parent_dp->d_children, dp, d_children_link); + } + } + + WITH_LOCK(dentry_hash_lock) { + // Remove all dp's child dentries from the hashtable. + dentry_children_remove(dp); + // Remove dp with outdated hash info from the hashtable. + LIST_REMOVE(dp, d_link); + // Update dp. + dp->d_path = strdup(path); + dp->d_parent = parent_dp; + // Insert dp updated hash info into the hashtable. + LIST_INSERT_HEAD(&dentry_hash_table[dentry_hash(dp->d_mount, path)], + dp, d_link); + } + + if (old_pdp) { + drele(old_pdp); + } + + free(old_path); } void dentry_remove(struct dentry *dp) { - mutex_lock(&dentry_hash_lock); - LIST_REMOVE(dp, d_link); - /* put it on a fake list for drele() to work*/ - LIST_INSERT_HEAD(&fake, dp, d_link); - mutex_unlock(&dentry_hash_lock); + mutex_lock(&dentry_hash_lock); + LIST_REMOVE(dp, d_link); + /* put it on a fake list for drele() to work*/ + LIST_INSERT_HEAD(&fake, dp, d_link); + mutex_unlock(&dentry_hash_lock); } void dref(struct dentry *dp) { - ASSERT(dp); - ASSERT(dp->d_refcnt > 0); + ASSERT(dp); + ASSERT(dp->d_refcnt > 0); - mutex_lock(&dentry_hash_lock); - dp->d_refcnt++; - mutex_unlock(&dentry_hash_lock); + mutex_lock(&dentry_hash_lock); + dp->d_refcnt++; + mutex_unlock(&dentry_hash_lock); } void drele(struct dentry *dp) { - ASSERT(dp); - ASSERT(dp->d_refcnt > 0); - - mutex_lock(&dentry_hash_lock); - if (--dp->d_refcnt) { - mutex_unlock(&dentry_hash_lock); - return; - } - LIST_REMOVE(dp, d_link); - vn_del_name(dp->d_vnode, dp); - - mutex_unlock(&dentry_hash_lock); - - if (dp->d_parent) { - WITH_LOCK(dp->d_parent->d_lock) { - // Remove dp from its parent's children list. - LIST_REMOVE(dp, d_children_link); - } - drele(dp->d_parent); - } - - vrele(dp->d_vnode); - - free(dp->d_path); - free(dp); + ASSERT(dp); + ASSERT(dp->d_refcnt > 0); + + mutex_lock(&dentry_hash_lock); + if (--dp->d_refcnt) { + mutex_unlock(&dentry_hash_lock); + return; + } + LIST_REMOVE(dp, d_link); + vn_del_name(dp->d_vnode, dp); + + mutex_unlock(&dentry_hash_lock); + + if (dp->d_parent) { + WITH_LOCK(dp->d_parent->d_lock) { + // Remove dp from its parent's children list. + LIST_REMOVE(dp, d_children_link); + } + drele(dp->d_parent); + } + + vrele(dp->d_vnode); + + free(dp->d_path); + free(dp); } void dentry_init(void) { - int i; + int i; - for (i = 0; i < DENTRY_BUCKETS; i++) { - LIST_INIT(&dentry_hash_table[i]); - } + for (i = 0; i < DENTRY_BUCKETS; i++) { + LIST_INIT(&dentry_hash_table[i]); + } } diff --git a/lib/vfscore/fops.c b/lib/vfscore/fops.c index 3a8f98b4..ab1f8cbb 100644 --- a/lib/vfscore/fops.c +++ b/lib/vfscore/fops.c @@ -140,17 +140,17 @@ int vfs_file::chmod(mode_t mode) bool vfs_file::map_page(uintptr_t off, mmu::hw_ptep<0> ptep, mmu::pt_element<0> pte, bool write, bool shared) { - return pagecache::get(this, off, ptep, pte, write, shared); + return pagecache::get(this, off, ptep, pte, write, shared); } bool vfs_file::put_page(void *addr, uintptr_t off, mmu::hw_ptep<0> ptep) { - return pagecache::release(this, addr, off, ptep); + return pagecache::release(this, addr, off, ptep); } void vfs_file::sync(off_t start, off_t end) { - pagecache::sync(this, start, end); + pagecache::sync(this, start, end); } // Locking: VOP_CACHE will call into the filesystem, and that can trigger an @@ -159,23 +159,23 @@ void vfs_file::sync(off_t start, off_t end) // because not all invalidations will be synchronous. int vfs_file::get_arcbuf(void* key, off_t offset) { - struct vnode *vp = f_dentry->d_vnode; + struct vnode *vp = f_dentry->d_vnode; - iovec io[1]; + iovec io[1]; - io[0].iov_base = key; - uio data; - data.uio_iov = io; - data.uio_iovcnt = 1; - data.uio_offset = offset; - data.uio_resid = mmu::page_size; - data.uio_rw = UIO_READ; + io[0].iov_base = key; + uio data; + data.uio_iov = io; + data.uio_iovcnt = 1; + data.uio_offset = offset; + data.uio_resid = mmu::page_size; + data.uio_rw = UIO_READ; - vn_lock(vp); - assert(VOP_CACHE(vp, this, &data) == 0); - vn_unlock(vp); + vn_lock(vp); + assert(VOP_CACHE(vp, this, &data) == 0); + vn_unlock(vp); - return (data.uio_resid != 0) ? -1 : 0; + return (data.uio_resid != 0) ? -1 : 0; } std::unique_ptr<mmu::file_vma> vfs_file::mmap(addr_range range, unsigned flags, unsigned perm, off_t offset) diff --git a/lib/vfscore/include/vfscore/dentry.h b/lib/vfscore/include/vfscore/dentry.h index a2545af8..f5850786 100644 --- a/lib/vfscore/include/vfscore/dentry.h +++ b/lib/vfscore/include/vfscore/dentry.h @@ -33,8 +33,8 @@ struct dentry { using dentry_ref = boost::intrusive_ptr<dentry>; extern "C" { - void dref(struct dentry* dp); - void drele(struct dentry* dp); + void dref(struct dentry* dp); + void drele(struct dentry* dp); }; inline void intrusive_ptr_add_ref(dentry* dp) { dref(dp); } diff --git a/lib/vfscore/include/vfscore/mount.h b/lib/vfscore/include/vfscore/mount.h index 7268d8ce..0e78929f 100644 --- a/lib/vfscore/include/vfscore/mount.h +++ b/lib/vfscore/include/vfscore/mount.h @@ -156,10 +156,10 @@ __END_DECLS namespace osv { struct mount_desc { - std::string special; - std::string path; - std::string type; - std::string options; + std::string special; + std::string path; + std::string type; + std::string options; }; std::vector<mount_desc> current_mounts(); diff --git a/lib/vfscore/lookup.c b/lib/vfscore/lookup.c index ad03fe25..30139a87 100644 --- a/lib/vfscore/lookup.c +++ b/lib/vfscore/lookup.c @@ -40,57 +40,57 @@ static ssize_t read_link(struct vnode *vp, char *buf, size_t bufsz, ssize_t *sz) { - struct iovec iov = {buf, bufsz}; - struct uio uio = {&iov, 1, 0, (ssize_t) bufsz, UIO_READ}; - int rc; + struct iovec iov = {buf, bufsz}; + struct uio uio = {&iov, 1, 0, (ssize_t) bufsz, UIO_READ}; + int rc; - *sz = 0; - vn_lock(vp); - rc = VOP_READLINK(vp, &uio); - vn_unlock(vp); + *sz = 0; + vn_lock(vp); + rc = VOP_READLINK(vp, &uio); + vn_unlock(vp); - if (rc != 0) { - return (rc); - } + if (rc != 0) { + return (rc); + } - *sz = bufsz - uio.uio_resid; - return (0); + *sz = bufsz - uio.uio_resid; + return (0); } int namei_follow_link(struct dentry *dp, char *node, char *name, char *fp, size_t mountpoint_len) { - std::unique_ptr<char []> link (new char[PATH_MAX]); - std::unique_ptr<char []> t (new char[PATH_MAX]); - char *lp; - int error; - ssize_t sz; - char *p; - int c; - - lp = link.get(); - error = read_link(dp->d_vnode, lp, PATH_MAX, &sz); - if (error != 0) { - return (error); - } - lp[sz] = 0; - - p = fp + mountpoint_len + strlen(node); - c = strlen(node) - strlen(name) - 1; - node[c] = 0; - - if (lp[0] == '/') { - strlcat(lp, p, PATH_MAX); - strlcpy(fp, lp, PATH_MAX); - } else { - strlcpy(t.get(), p, PATH_MAX); - strlcpy(node, fp, mountpoint_len + c + 1); - path_conv(node, lp, fp); - strlcat(fp, t.get(), PATH_MAX); - } - node[0] = 0; - name[0] = 0; - return (0); + std::unique_ptr<char []> link (new char[PATH_MAX]); + std::unique_ptr<char []> t (new char[PATH_MAX]); + char *lp; + int error; + ssize_t sz; + char *p; + int c; + + lp = link.get(); + error = read_link(dp->d_vnode, lp, PATH_MAX, &sz); + if (error != 0) { + return (error); + } + lp[sz] = 0; + + p = fp + mountpoint_len + strlen(node); + c = strlen(node) - strlen(name) - 1; + node[c] = 0; + + if (lp[0] == '/') { + strlcat(lp, p, PATH_MAX); + strlcpy(fp, lp, PATH_MAX); + } else { + strlcpy(t.get(), p, PATH_MAX); + strlcpy(node, fp, mountpoint_len + c + 1); + path_conv(node, lp, fp); + strlcat(fp, t.get(), PATH_MAX); + } + node[0] = 0; + name[0] = 0; + return (0); } /* * Convert a pathname into a pointer to a dentry @@ -101,137 +101,137 @@ namei_follow_link(struct dentry *dp, char *node, char *name, char *fp, size_t mo int namei(const char *path, struct dentry **dpp) { - char *p; - char node[PATH_MAX]; - char name[PATH_MAX]; - std::unique_ptr<char []> fp (new char [PATH_MAX]); - std::unique_ptr<char []> t (new char [PATH_MAX]); - struct mount *mp; - struct dentry *dp, *ddp; - struct vnode *dvp, *vp; - int error, i; - int links_followed; - bool need_continue; - - DPRINTF(VFSDB_VNODE, ("namei: path=%s\n", path)); - - links_followed = 0; - strlcpy(fp.get(), path, PATH_MAX); - - do { - need_continue = false; - /* - * Convert a full path name to its mount point and - * the local node in the file system. - */ - if (vfs_findroot(fp.get(), &mp, &p)) { - return ENOTDIR; - } - int mountpoint_len = p - fp.get() - 1; - strlcpy(node, "/", sizeof(node)); - strlcat(node, p, sizeof(node)); - dp = dentry_lookup(mp, node); - if (dp) { - /* vnode is already active. */ - *dpp = dp; - return 0; - } - /* - * Find target vnode, started from root directory. - * This is done to attach the fs specific data to - * the target vnode. - */ - ddp = mp->m_root; - if (!ddp) { - sys_panic("VFS: no root"); - } - dref(ddp); - - node[0] = '\0'; - - while (*p != '\0') { - /* - * Get lower directory/file name. - */ - while (*p == '/') { - p++; - } - - if (*p == '\0') { - break; - } - - for (i = 0; i < PATH_MAX; i++) { - if (*p == '\0' || *p == '/') { - break; - } - name[i] = *p++; - } - name[i] = '\0'; - - /* - * Get a vnode for the target. - */ - strlcat(node, "/", sizeof(node)); - strlcat(node, name, sizeof(node)); - dvp = ddp->d_vnode; - vn_lock(dvp); - dp = dentry_lookup(mp, node); - if (dp == nullptr) { - /* Find a vnode in this directory. */ - error = VOP_LOOKUP(dvp, name, &vp); - if (error) { - vn_unlock(dvp); - drele(ddp); - return error; - } - - dp = dentry_alloc(ddp, vp, node); - vput(vp); - - if (!dp) { - vn_unlock(dvp); - drele(ddp); - return ENOMEM; - } - } - vn_unlock(dvp); - drele(ddp); - ddp = dp; - - if (dp->d_vnode->v_type == VLNK) { - error = namei_follow_link(dp, node, name, fp.get(), mountpoint_len); - if (error) { - drele(dp); - return (error); - } - - drele(dp); - - p = fp.get(); - dp = nullptr; - ddp = nullptr; - vp = nullptr; - dvp = nullptr; - name[0] = 0; - node[0] = 0; - - if (++links_followed >= MAXSYMLINKS) { - return (ELOOP); - } - need_continue = true; - break; - } - - if (*p == '/' && ddp->d_vnode->v_type != VDIR) { - drele(ddp); - return ENOTDIR; - } - } - } while (need_continue == true); - - *dpp = dp; - return 0; + char *p; + char node[PATH_MAX]; + char name[PATH_MAX]; + std::unique_ptr<char []> fp (new char [PATH_MAX]); + std::unique_ptr<char []> t (new char [PATH_MAX]); + struct mount *mp; + struct dentry *dp, *ddp; + struct vnode *dvp, *vp; + int error, i; + int links_followed; + bool need_continue; + + DPRINTF(VFSDB_VNODE, ("namei: path=%s\n", path)); + + links_followed = 0; + strlcpy(fp.get(), path, PATH_MAX); + + do { + need_continue = false; + /* + * Convert a full path name to its mount point and + * the local node in the file system. + */ + if (vfs_findroot(fp.get(), &mp, &p)) { + return ENOTDIR; + } + int mountpoint_len = p - fp.get() - 1; + strlcpy(node, "/", sizeof(node)); + strlcat(node, p, sizeof(node)); + dp = dentry_lookup(mp, node); + if (dp) { + /* vnode is already active. */ + *dpp = dp; + return 0; + } + /* + * Find target vnode, started from root directory. + * This is done to attach the fs specific data to + * the target vnode. + */ + ddp = mp->m_root; + if (!ddp) { + sys_panic("VFS: no root"); + } + dref(ddp); + + node[0] = '\0'; + + while (*p != '\0') { + /* + * Get lower directory/file name. + */ + while (*p == '/') { + p++; + } + + if (*p == '\0') { + break; + } + + for (i = 0; i < PATH_MAX; i++) { + if (*p == '\0' || *p == '/') { + break; + } + name[i] = *p++; + } + name[i] = '\0'; + + /* + * Get a vnode for the target. + */ + strlcat(node, "/", sizeof(node)); + strlcat(node, name, sizeof(node)); + dvp = ddp->d_vnode; + vn_lock(dvp); + dp = dentry_lookup(mp, node); + if (dp == nullptr) { + /* Find a vnode in this directory. */ + error = VOP_LOOKUP(dvp, name, &vp); + if (error) { + vn_unlock(dvp); + drele(ddp); + return error; + } + + dp = dentry_alloc(ddp, vp, node); + vput(vp); + + if (!dp) { + vn_unlock(dvp); + drele(ddp); + return ENOMEM; + } + } + vn_unlock(dvp); + drele(ddp); + ddp = dp; + + if (dp->d_vnode->v_type == VLNK) { + error = namei_follow_link(dp, node, name, fp.get(), mountpoint_len); + if (error) { + drele(dp); + return (error); + } + + drele(dp); + + p = fp.get(); + dp = nullptr; + ddp = nullptr; + vp = nullptr; + dvp = nullptr; + name[0] = 0; + node[0] = 0; + + if (++links_followed >= MAXSYMLINKS) { + return (ELOOP); + } + need_continue = true; + break; + } + + if (*p == '/' && ddp->d_vnode->v_type != VDIR) { + drele(ddp); + return ENOTDIR; + } + } + } while (need_continue == true); + + *dpp = dp; + return 0; } /* @@ -244,67 +244,67 @@ namei(const char *path, struct dentry **dpp) int namei_last_nofollow(char *path, struct dentry *ddp, struct dentry **dpp) { - char *name; - int error; - struct mount *mp; - char *p; - struct dentry *dp; - struct vnode *dvp; - struct vnode *vp; - std::unique_ptr<char []> node (new char[PATH_MAX]); - - dvp = nullptr; - - if (path[0] != '/') { - return (ENOTDIR); - } - - name = strrchr(path, '/'); - if (name == nullptr) { - return (ENOENT); - } - name++; - - error = vfs_findroot(path, &mp, &p); - if (error != 0) { - return (ENOTDIR); - } - - strlcpy(node.get(), "/", PATH_MAX); - strlcat(node.get(), p, PATH_MAX); - - // We want to treat things like /tmp/ the same as /tmp. Best way to do that - // is to ignore the last character, except when we're stating the root. - auto l = strlen(node.get()) - 1; - if (l && node.get()[l] == '/') { - node.get()[l] = '\0'; - } - - dvp = ddp->d_vnode; - vn_lock(dvp); - dp = dentry_lookup(mp, node.get()); - if (dp == nullptr) { - error = VOP_LOOKUP(dvp, name, &vp); - if (error != 0) { - goto out; - } - - dp = dentry_alloc(ddp, vp, node.get()); - vput(vp); - - if (dp == nullptr) { - error = ENOMEM; - goto out; - } - } - - *dpp = dp; - error = 0; + char *name; + int error; + struct mount *mp; + char *p; + struct dentry *dp; + struct vnode *dvp; + struct vnode *vp; + std::unique_ptr<char []> node (new char[PATH_MAX]); + + dvp = nullptr; + + if (path[0] != '/') { + return (ENOTDIR); + } + + name = strrchr(path, '/'); + if (name == nullptr) { + return (ENOENT); + } + name++; + + error = vfs_findroot(path, &mp, &p); + if (error != 0) { + return (ENOTDIR); + } + + strlcpy(node.get(), "/", PATH_MAX); + strlcat(node.get(), p, PATH_MAX); + + // We want to treat things like /tmp/ the same as /tmp. Best way to do that + // is to ignore the last character, except when we're stating the root. + auto l = strlen(node.get()) - 1; + if (l && node.get()[l] == '/') { + node.get()[l] = '\0'; + } + + dvp = ddp->d_vnode; + vn_lock(dvp); + dp = dentry_lookup(mp, node.get()); + if (dp == nullptr) { + error = VOP_LOOKUP(dvp, name, &vp); + if (error != 0) { + goto out; + } + + dp = dentry_alloc(ddp, vp, node.get()); + vput(vp); + + if (dp == nullptr) { + error = ENOMEM; + goto out; + } + } + + *dpp = dp; + error = 0; out: - if (dvp != nullptr) { - vn_unlock(dvp); - } - return (error); + if (dvp != nullptr) { + vn_unlock(dvp); + } + return (error); } /* @@ -320,48 +320,48 @@ out: int lookup(char *path, struct dentry **dpp, char **name) { - char buf[PATH_MAX]; - char root[] = "/"; - char *file, *dir; - struct dentry *dp; - int error; - - DPRINTF(VFSDB_VNODE, ("lookup: path=%s\n", path)); - - /* - * Get the path for directory. - */ - strlcpy(buf, path, sizeof(buf)); - file = strrchr(buf, '/'); - if (!buf[0]) { - return ENOTDIR; - } - if (file == buf) { - dir = root; - } else { - *file = '\0'; - dir = buf; - } - /* - * Get the vnode for directory - */ - if ((error = namei(dir, &dp)) != 0) { - return error; - } - if (dp->d_vnode->v_type != VDIR) { - drele(dp); - return ENOTDIR; - } - - *dpp = dp; - - if (name) { - /* - * Get the file name - */ - *name = strrchr(path, '/') + 1; - } - return 0; + char buf[PATH_MAX]; + char root[] = "/"; + char *file, *dir; + struct dentry *dp; + int error; + + DPRINTF(VFSDB_VNODE, ("lookup: path=%s\n", path)); + + /* + * Get the path for directory. + */ + strlcpy(buf, path, sizeof(buf)); + file = strrchr(buf, '/'); + if (!buf[0]) { + return ENOTDIR; + } + if (file == buf) { + dir = root; + } else { + *file = '\0'; + dir = buf; + } + /* + * Get the vnode for directory + */ + if ((error = namei(dir, &dp)) != 0) { + return error; + } + if (dp->d_vnode->v_type != VDIR) { + drele(dp); + return ENOTDIR; + } + + *dpp = dp; + + if (name) { + /* + * Get the file name + */ + *name = strrchr(path, '/') + 1; + } + return 0; } /* @@ -371,5 +371,5 @@ lookup(char *path, struct dentry **dpp, char **name) void lookup_init(void) { - dentry_init(); + dentry_init(); } diff --git a/lib/vfscore/main.c b/lib/vfscore/main.c index cd141117..8d9dc33a 100644 --- a/lib/vfscore/main.c +++ b/lib/vfscore/main.c @@ -92,7 +92,7 @@ std::atomic<mode_t> global_umask{S_IWGRP | S_IWOTH}; static inline mode_t apply_umask(mode_t mode) { - return mode & ~global_umask.load(std::memory_order_relaxed); + return mode & ~global_umask.load(std::memory_order_relaxed); } TRACEPOINT(trace_vfs_open, "\"%s\" 0x%x 0%0o", const char*, int, mode_t); @@ -104,99 +104,99 @@ struct task *main_task; /* we only have a single process */ extern "C" int open(const char *pathname, int flags, ...) { - mode_t mode = 0; - if (flags & O_CREAT) { - va_list ap; - va_start(ap, flags); - mode = apply_umask(va_arg(ap, mode_t)); - va_end(ap); - } - - trace_vfs_open(pathname, flags, mode); - - struct task *t = main_task; - char path[PATH_MAX]; - struct file *fp; - int fd, error; - int acc; - - acc = 0; - switch (flags & O_ACCMODE) { - case O_RDONLY: - acc = VREAD; - break; - case O_WRONLY: - acc = VWRITE; - break; - case O_RDWR: - acc = VREAD | VWRITE; - break; - } - - error = task_conv(t, pathname, acc, path); - if (error) - goto out_errno; - - error = sys_open(path, flags, mode, &fp); - if (error) - goto out_errno; - - error = fdalloc(fp, &fd); - if (error) - goto out_fput; - fdrop(fp); - trace_vfs_open_ret(fd); - return fd; - - out_fput: - fdrop(fp); - out_errno: - errno = error; - trace_vfs_open_err(error); - return -1; + mode_t mode = 0; + if (flags & O_CREAT) { + va_list ap; + va_start(ap, flags); + mode = apply_umask(va_arg(ap, mode_t)); + va_end(ap); + } + + trace_vfs_open(pathname, flags, mode); + + struct task *t = main_task; + char path[PATH_MAX]; + struct file *fp; + int fd, error; + int acc; + + acc = 0; + switch (flags & O_ACCMODE) { + case O_RDONLY: + acc = VREAD; + break; + case O_WRONLY: + acc = VWRITE; + break; + case O_RDWR: + acc = VREAD | VWRITE; + break; + } + + error = task_conv(t, pathname, acc, path); + if (error) + goto out_errno; + + error = sys_open(path, flags, mode, &fp); + if (error) + goto out_errno; + + error = fdalloc(fp, &fd); + if (error) + goto out_fput; + fdrop(fp); + trace_vfs_open_ret(fd); + return fd; + + out_fput: + fdrop(fp); + out_errno: + errno = error; + trace_vfs_open_err(error); + return -1; } LFS64(open); int openat(int dirfd, const char *pathname, int flags, ...) { - mode_t mode = 0; - if (flags & O_CREAT) { - va_list ap; - va_start(ap, flags); - mode = apply_umask(va_arg(ap, mode_t)); - va_end(ap); - } + mode_t mode = 0; + if (flags & O_CREAT) { + va_list ap; + va_start(ap, flags); + mode = apply_umask(va_arg(ap, mode_t)); + va_end(ap); + } - if (pathname[0] == '/' || dirfd == AT_FDCWD) { - return open(pathname, flags, mode); - } + if (pathname[0] == '/' || dirfd == AT_FDCWD) { + return open(pathname, flags, mode); + } - struct file *fp; - int error = fget(dirfd, &fp); - if (error) { - errno = error; - return -1; - } + struct file *fp; + int error = fget(dirfd, &fp); + if (error) { + errno = error; + return -1; + } - struct vnode *vp = fp->f_dentry->d_vnode; - vn_lock(vp); + struct vnode *vp = fp->f_dentry->d_vnode; + vn_lock(vp); - std::unique_ptr<char []> up (new char[PATH_MAX]); - char *p = up.get(); + std::unique_ptr<char []> up (new char[PATH_MAX]); + char *p = up.get(); - /* build absolute path */ - strlcpy(p, fp->f_dentry->d_mount->m_path, PATH_MAX); - strlcat(p, fp->f_dentry->d_path, PATH_MAX); - strlcat(p, "/", PATH_MAX); - strlcat(p, pathname, PATH_MAX); + /* build absolute path */ + strlcpy(p, fp->f_dentry->d_mount->m_path, PATH_MAX); + strlcat(p, fp->f_dentry->d_path, PATH_MAX); + strlcat(p, "/", PATH_MAX); + strlcat(p, pathname, PATH_MAX); - error = open(p, flags, mode); + error = open(p, flags, mode); - vn_unlock(vp); - fdrop(fp); + vn_unlock(vp); + fdrop(fp); - return error; + return error; } LFS64(openat); @@ -206,23 +206,23 @@ LFS64(openat); // by a call to __open_2(), which verifies it isn't called with O_CREATE. extern "C" int __open_2(const char *pathname, int flags) { - assert(!(flags & O_CREAT)); - return open(pathname, flags, 0); + assert(!(flags & O_CREAT)); + return open(pathname, flags, 0); } extern "C" int __open64_2(const char *file, int flags) { - if (flags & O_CREAT) { - errno = EINVAL; - return -1; - } + if (flags & O_CREAT) { + errno = EINVAL; + return -1; + } - return open64(file, flags); + return open64(file, flags); } int creat(const char *pathname, mode_t mode) { - return open(pathname, O_CREAT|O_WRONLY|O_TRUNC, mode); + return open(pathname, O_CREAT|O_WRONLY|O_TRUNC, mode); } LFS64(creat); @@ -232,20 +232,20 @@ TRACEPOINT(trace_vfs_close_err, "%d", int); int close(int fd) { - int error; + int error; - trace_vfs_close(fd); - error = fdclose(fd); - if (error) - goto out_errno; + trace_vfs_close(fd); + error = fdclose(fd); + if (error) + goto out_errno; - trace_vfs_close_ret(); - return 0; + trace_vfs_close_ret(); + return 0; - out_errno: - trace_vfs_close_err(error); - errno = error; - return -1; + out_errno: + trace_vfs_close_err(error); + errno = error; + return -1; } TRACEPOINT(trace_vfs_mknod, "\"%s\" 0%0o 0x%x", const char*, mode_t, dev_t); @@ -256,31 +256,31 @@ TRACEPOINT(trace_vfs_mknod_err, "%d", int); extern "C" int __xmknod(int ver, const char *pathname, mode_t mode, dev_t *dev) { - assert(ver == 0); // On x86-64 Linux, _MKNOD_VER_LINUX is 0. - struct task *t = main_task; - char path[PATH_MAX]; - int error; + assert(ver == 0); // On x86-64 Linux, _MKNOD_VER_LINUX is 0. + struct task *t = main_task; + char path[PATH_MAX]; + int error; - trace_vfs_mknod(pathname, mode, *dev); - if ((error = task_conv(t, pathname, VWRITE, path)) != 0) - goto out_errno; + trace_vfs_mknod(pathname, mode, *dev); + if ((error = task_conv(t, pathname, VWRITE, path)) != 0) + goto out_errno; - error = sys_mknod(path, mode); - if (error) - goto out_errno; + error = sys_mknod(path, mode); + if (error) + goto out_errno; - trace_vfs_mknod_ret(); - return 0; + trace_vfs_mknod_ret(); + return 0; - out_errno: - trace_vfs_mknod_err(error); - errno = error; - return -1; + out_errno: + trace_vfs_mknod_err(error); + errno = error; + return -1; } int mknod(const char *pathname, mode_t mode, dev_t dev) { - return __xmknod(0, pathname, mode, &dev); + return __xmknod(0, pathname, mode, &dev); } @@ -290,27 +290,27 @@ TRACEPOINT(trace_vfs_lseek_err, "%d", int); off_t lseek(int fd, off_t offset, int whence) { - struct file *fp; - off_t org; - int error; + struct file *fp; + off_t org; + int error; - trace_vfs_lseek(fd, offset, whence); - error = fget(fd, &fp); - if (error) - goto out_errno; + trace_vfs_lseek(fd, offset, whence); + error = fget(fd, &fp); + if (error) + goto out_errno; - error = sys_lseek(fp, offset, whence, &org); - fdrop(fp); + error = sys_lseek(fp, offset, whence, &org); + fdrop(fp); - if (error) - goto out_errno; - trace_vfs_lseek_ret(org); - return org; + if (error) + goto out_errno; + trace_vfs_lseek_ret(org); + return org; - out_errno: - trace_vfs_lseek_err(error); - errno = error; - return -1; + out_errno: + trace_vfs_lseek_err(error); + errno = error; + return -1; } LFS64(lseek); @@ -326,46 +326,46 @@ TRACEPOINT(trace_vfs_pread_err, "%d", int); // In FreeBSD, dofilewrite() and dofileread() (sys_generic.c) do this too. static inline bool has_error(int error, int bytes) { - return error && ( - (bytes == 0) || - (error != EWOULDBLOCK && error != EINTR && error != ERESTART)); + return error && ( + (bytes == 0) || + (error != EWOULDBLOCK && error != EINTR && error != ERESTART)); } ssize_t pread(int fd, void *buf, size_t count, off_t offset) { - trace_vfs_pread(fd, buf, count, offset); - struct iovec iov = { - .iov_base = buf, - .iov_len = count, - }; - struct file *fp; - size_t bytes; - int error; + trace_vfs_pread(fd, buf, count, offset); + struct iovec iov = { + .iov_base = buf, + .iov_len = count, + }; + struct file *fp; + size_t bytes; + int error; - error = fget(fd, &fp); - if (error) - goto out_errno; + error = fget(fd, &fp); + if (error) + goto out_errno; - error = sys_read(fp, &iov, 1, offset, &bytes); - fdrop(fp); + error = sys_read(fp, &iov, 1, offset, &bytes); + fdrop(fp); - if (has_error(error, bytes)) - goto out_errno; - trace_vfs_pread_ret(bytes); - return bytes; + if (has_error(error, bytes)) + goto out_errno; + trace_vfs_pread_ret(bytes); + return bytes; - out_errno: - trace_vfs_pread_err(error); - errno = error; - return -1; + out_errno: + trace_vfs_pread_err(error); + errno = error; + return -1; } LFS64(pread); ssize_t read(int fd, void *buf, size_t count) { - return pread(fd, buf, count, -1); + return pread(fd, buf, count, -1); } TRACEPOINT(trace_vfs_pwrite, "%d %p 0x%x 0x%x", int, const void*, size_t, off_t); @@ -374,67 +374,67 @@ TRACEPOINT(trace_vfs_pwrite_err, "%d", int); ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset) { - trace_vfs_pwrite(fd, buf, count, offset); - struct iovec iov = { - .iov_base = (void *)buf, - .iov_len = count, - }; - struct file *fp; - size_t bytes; - int error; + trace_vfs_pwrite(fd, buf, count, offset); + struct iovec iov = { + .iov_base = (void *)buf, + .iov_len = count, + }; + struct file *fp; + size_t bytes; + int error; - error = fget(fd, &fp); - if (error) - goto out_errno; + error = fget(fd, &fp); + if (error) + goto out_errno; - error = sys_write(fp, &iov, 1, offset, &bytes); - fdrop(fp); + error = sys_write(fp, &iov, 1, offset, &bytes); + fdrop(fp); - if (has_error(error, bytes)) - goto out_errno; - trace_vfs_pwrite_ret(bytes); - return bytes; + if (has_error(error, bytes)) + goto out_errno; + trace_vfs_pwrite_ret(bytes); + return bytes; - out_errno: - trace_vfs_pwrite_err(error); - errno = error; - return -1; + out_errno: + trace_vfs_pwrite_err(error); + errno = error; + return -1; } LFS64(pwrite); ssize_t write(int fd, const void *buf, size_t count) { - return pwrite(fd, buf, count, -1); + return pwrite(fd, buf, count, -1); } ssize_t preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset) { - struct file *fp; - size_t bytes; - int error; + struct file *fp; + size_t bytes; + int error; - error = fget(fd, &fp); - if (error) - goto out_errno; + error = fget(fd, &fp); + if (error) + goto out_errno; - error = sys_read(fp, iov, iovcnt, offset, &bytes); - fdrop(fp); + error = sys_read(fp, iov, iovcnt, offset, &bytes); + fdrop(fp); - if (has_error(error, bytes)) - goto out_errno; - return bytes; + if (has_error(error, bytes)) + goto out_errno; + return bytes; - out_errno: - errno = error; - return -1; + out_errno: + errno = error; + return -1; } LFS64(preadv); ssize_t readv(int fd, const struct iovec *iov, int iovcnt) { - return preadv(fd, iov, iovcnt, -1); + return preadv(fd, iov, iovcnt, -1); } TRACEPOINT(trace_vfs_pwritev, "%d %p 0x%x 0x%x", int, const struct iovec*, int, off_t); @@ -443,33 +443,33 @@ TRACEPOINT(trace_vfs_pwritev_err, "%d", int); ssize_t pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset) { - struct file *fp; - size_t bytes; - int error; + struct file *fp; + size_t bytes; + int error; - trace_vfs_pwritev(fd, iov, iovcnt, offset); - error = fget(fd, &fp); - if (error) - goto out_errno; + trace_vfs_pwritev(fd, iov, iovcnt, offset); + error = fget(fd, &fp); + if (error) + goto out_errno; - error = sys_write(fp, iov, iovcnt, offset, &bytes); - fdrop(fp); + error = sys_write(fp, iov, iovcnt, offset, &bytes); + fdrop(fp); - if (has_error(error, bytes)) - goto out_errno; - trace_vfs_pwritev_ret(bytes); - return bytes; + if (has_error(error, bytes)) + goto out_errno; + trace_vfs_pwritev_ret(bytes); + return bytes; - out_errno: - trace_vfs_pwritev_err(error); - errno = error; - return -1; + out_errno: + trace_vfs_pwritev_err(error); + errno = error; + return -1; } LFS64(pwritev); ssize_t writev(int fd, const struct iovec *iov, int iovcnt) { - return pwritev(fd, iov, iovcnt, -1); + return pwritev(fd, iov, iovcnt, -1); } TRACEPOINT(trace_vfs_ioctl, "%d 0x%x", int, unsigned long); @@ -478,35 +478,35 @@ TRACEPOINT(trace_vfs_ioctl_err, "%d", int); int ioctl(int fd, unsigned long int request, ...) { - struct file *fp; - int error; - va_list ap; - void* arg; + struct file *fp; + int error; + va_list ap; + void* arg; - trace_vfs_ioctl(fd, request); - /* glibc ABI provides a variadic prototype for ioctl so we need to agree - * with it, since we now include sys/ioctl.h - * read the first argument and pass it to sys_ioctl() */ - va_start(ap, request); - arg = va_arg(ap, void*); - va_end(ap); + trace_vfs_ioctl(fd, request); + /* glibc ABI provides a variadic prototype for ioctl so we need to agree + * with it, since we now include sys/ioctl.h + * read the first argument and pass it to sys_ioctl() */ + va_start(ap, request); + arg = va_arg(ap, void*); + va_end(ap); - error = fget(fd, &fp); - if (error) - goto out_errno; + error = fget(fd, &fp); + if (error) + goto out_errno; - error = sys_ioctl(fp, request, arg); - fdrop(fp); + error = sys_ioctl(fp, request, arg); + fdrop(fp); - if (error) - goto out_errno; - trace_vfs_ioctl_ret(); - return 0; + if (error) + goto out_errno; + trace_vfs_ioctl_ret(); + return 0; - out_errno: - trace_vfs_ioctl_err(error); - errno = error; - return -1; + out_errno: + trace_vfs_ioctl_err(error); + errno = error; + return -1; } TRACEPOINT(trace_vfs_fsync, "%d", int); @@ -515,32 +515,32 @@ TRACEPOINT(trace_vfs_fsync_err, "%d", int); int fsync(int fd) { - struct file *fp; - int error; + struct file *fp; + int error; - trace_vfs_fsync(fd); - error = fget(fd, &fp); - if (error) - goto out_errno; + trace_vfs_fsync(fd); + error = fget(fd, &fp); + if (error) + goto out_errno; - error = sys_fsync(fp); - fdrop(fp); + error = sys_fsync(fp); + fdrop(fp); - if (error) - goto out_errno; - trace_vfs_fsync_ret(); - return 0; + if (error) + goto out_errno; + trace_vfs_fsync_ret(); + return 0; - out_errno: - trace_vfs_fsync_err(error); - errno = error; - return -1; + out_errno: + trace_vfs_fsync_err(error); + errno = error; + return -1; } int fdatasync(int fd) { - // TODO: See if we can do less than fsync(). - return fsync(fd); + // TODO: See if we can do less than fsync(). + return fsync(fd); } TRACEPOINT(trace_vfs_fstat, "%d %p", int, struct stat*); @@ -550,27 +550,27 @@ TRACEPOINT(trace_vfs_fstat_err, "%d", int); extern "C" int __fxstat(int ver, int fd, struct stat *st) { - struct file *fp; - int error; + struct file *fp; + int error; - trace_vfs_fstat(fd, st); + trace_vfs_fstat(fd, st); - error = fget(fd, &fp); - if (error) - goto out_errno; + error = fget(fd, &fp); + if (error) + goto out_errno; - error = sys_fstat(fp, st); - fdrop(fp); + error = sys_fstat(fp, st); + fdrop(fp); - if (error) - goto out_errno; - trace_vfs_fstat_ret(); - return 0; + if (error) + goto out_errno; + trace_vfs_fstat_ret(); + return 0; - out_errno: - trace_vfs_fstat_err(error); - errno = error; - return -1; + out_errno: + trace_vfs_fstat_err(error); + errno = error; + return -1; } LFS64(__fxstat); @@ -578,52 +578,52 @@ LFS64(__fxstat); extern "C" int fstat(int fd, struct stat *st) { - return __fxstat(1, fd, st); + return __fxstat(1, fd, st); } LFS64(fstat); extern "C" int __fxstatat(int ver, int dirfd, const char *pathname, struct stat *st, - int flags) + int flags) { - if (flags & AT_SYMLINK_NOFOLLOW) { - UNIMPLEMENTED("fstatat() with AT_SYMLINK_NOFOLLOW"); - } + if (flags & AT_SYMLINK_NOFOLLOW) { + UNIMPLEMENTED("fstatat() with AT_SYMLINK_NOFOLLOW"); + } - if (pathname[0] == '/' || dirfd == AT_FDCWD) { - return stat(pathname, st); - } - // If AT_EMPTY_PATH and pathname is an empty string, fstatat() operates on - // dirfd itself, and in that case it doesn't have to be a directory. - if ((flags & AT_EMPTY_PATH) && !pathname[0]) { - return fstat(dirfd, st); - } + if (pathname[0] == '/' || dirfd == AT_FDCWD) { + return stat(pathname, st); + } + // If AT_EMPTY_PATH and pathname is an empty string, fstatat() operates on + // dirfd itself, and in that case it doesn't have to be a directory. + if ((flags & AT_EMPTY_PATH) && !pathname[0]) { + return fstat(dirfd, st); + } - struct file *fp; - int error = fget(dirfd, &fp); - if (error) { - errno = error; - return -1; - } + struct file *fp; + int error = fget(dirfd, &fp); + if (error) { + errno = error; + return -1; + } - struct vnode *vp = fp->f_dentry->d_vnode; - vn_lock(vp); + struct vnode *vp = fp->f_dentry->d_vnode; + vn_lock(vp); - std::unique_ptr<char []> up (new char[PATH_MAX]); - char *p = up.get(); - /* build absolute path */ - strlcpy(p, fp->f_dentry->d_mount->m_path, PATH_MAX); - strlcat(p, fp->f_dentry->d_path, PATH_MAX); - strlcat(p, "/", PATH_MAX); - strlcat(p, pathname, PATH_MAX); + std::unique_ptr<char []> up (new char[PATH_MAX]); + char *p = up.get(); + /* build absolute path */ + strlcpy(p, fp->f_dentry->d_mount->m_path, PATH_MAX); + strlcat(p, fp->f_dentry->d_path, PATH_MAX); + strlcat(p, "/", PATH_MAX); + strlcat(p, pathname, PATH_MAX); - error = stat(p, st); + error = stat(p, st); - vn_unlock(vp); - fdrop(fp); + vn_unlock(vp); + fdrop(fp); - return error; + return error; } LFS64(__fxstatat); @@ -631,29 +631,29 @@ LFS64(__fxstatat); extern "C" int fstatat(int dirfd, const char *path, struct stat *st, int flags) { - return __fxstatat(1, dirfd, path, st, flags); + return __fxstatat(1, dirfd, path, st, flags); } LFS64(fstatat); extern "C" int flock(int fd, int operation) { - if (!fileref_from_fd(fd)) { - return libc_error(EBADF); - } + if (!fileref_from_fd(fd)) { + return libc_error(EBADF); + } - switch (operation) { - case LOCK_SH: - case LOCK_SH | LOCK_NB: - case LOCK_EX: - case LOCK_EX | LOCK_NB: - case LOCK_UN: - break; - default: - return libc_error(EINVAL); - } + switch (operation) { + case LOCK_SH: + case LOCK_SH | LOCK_NB: + case LOCK_EX: + case LOCK_EX | LOCK_NB: + case LOCK_UN: + break; + default: + return libc_error(EINVAL); + } - return 0; + return 0; } TRACEPOINT(trace_vfs_readdir, "%d %p", int, dirent*); @@ -662,152 +662,152 @@ TRACEPOINT(trace_vfs_readdir_err, "%d", int); struct __dirstream { - int fd; + int fd; }; DIR *opendir(const char *path) { - DIR *dir = new DIR; + DIR *dir = new DIR; - if (!dir) - return libc_error_ptr<DIR>(ENOMEM); + if (!dir) + return libc_error_ptr<DIR>(ENOMEM); - dir->fd = open(path, O_RDONLY); - if (dir->fd < 0) { - delete dir; - return nullptr; - } - return dir; + dir->fd = open(path, O_RDONLY); + if (dir->fd < 0) { + delete dir; + return nullptr; + } + return dir; } DIR *fdopendir(int fd) { - DIR *dir; - struct stat st; - if (fstat(fd, &st) < 0) { - return nullptr; - } - if (!S_ISDIR(st.st_mode)) { - errno = ENOTDIR; - return nullptr; - } - dir = new DIR; - dir->fd = fd; - return dir; + DIR *dir; + struct stat st; + if (fstat(fd, &st) < 0) { + return nullptr; + } + if (!S_ISDIR(st.st_mode)) { + errno = ENOTDIR; + return nullptr; + } + dir = new DIR; + dir->fd = fd; + return dir; } int dirfd(DIR *dirp) { - if (!dirp) { - return libc_error(EINVAL); - } + if (!dirp) { + return libc_error(EINVAL); + } - return dirp->fd; + return dirp->fd; } int closedir(DIR *dir) { - close(dir->fd); - delete dir; - return 0; + close(dir->fd); + delete dir; + return 0; } struct dirent *readdir(DIR *dir) { - static __thread struct dirent entry, *result; - int ret; + static __thread struct dirent entry, *result; + int ret; - ret = readdir_r(dir, &entry, &result); - if (ret) - return libc_error_ptr<struct dirent>(ret); + ret = readdir_r(dir, &entry, &result); + if (ret) + return libc_error_ptr<struct dirent>(ret); - errno = 0; - return result; + errno = 0; + return result; } int readdir_r(DIR *dir, struct dirent *entry, struct dirent **result) { - int error; - struct file *fp; - - trace_vfs_readdir(dir->fd, entry); - error = fget(dir->fd, &fp); - if (error) { - trace_vfs_readdir_err(error); - } else { - error = sys_readdir(fp, entry); - fdrop(fp); - if (error) { - trace_vfs_readdir_err(error); - } else { - trace_vfs_readdir_ret(); - } - } - // Our dirent has (like Linux) a d_reclen field, but a constant size. - entry->d_reclen = sizeof(*entry); - - if (error) { - *result = nullptr; - } else { - *result = entry; - } - return error == ENOENT ? 0 : error; + int error; + struct file *fp; + + trace_vfs_readdir(dir->fd, entry); + error = fget(dir->fd, &fp); + if (error) { + trace_vfs_readdir_err(error); + } else { + error = sys_readdir(fp, entry); + fdrop(fp); + if (error) { + trace_vfs_readdir_err(error); + } else { + trace_vfs_readdir_ret(); + } + } + // Our dirent has (like Linux) a d_reclen field, but a constant size. + entry->d_reclen = sizeof(*entry); + + if (error) { + *result = nullptr; + } else { + *result = entry; + } + return error == ENOENT ? 0 : error; } // FIXME: in 64bit dirent64 and dirent are identical, so it's safe to alias #undef readdir64_r extern "C" int readdir64_r(DIR *dir, struct dirent64 *entry, - struct dirent64 **result) - __attribute__((alias("readdir_r"))); + struct dirent64 **result) + __attribute__((alias("readdir_r"))); #undef readdir64 extern "C" struct dirent *readdir64(DIR *dir) __attribute__((alias("readdir"))); void rewinddir(DIR *dirp) { - struct file *fp; + struct file *fp; - auto error = fget(dirp->fd, &fp); - if (error) { - // POSIX specifies that what rewinddir() does in the case of error - // is undefined... - return; - } + auto error = fget(dirp->fd, &fp); + if (error) { + // POSIX specifies that what rewinddir() does in the case of error + // is undefined... + return; + } - sys_rewinddir(fp); - // Again, error code from sys_rewinddir() is ignored. - fdrop(fp); + sys_rewinddir(fp); + // Again, error code from sys_rewinddir() is ignored. + fdrop(fp); } long telldir(DIR *dirp) { - struct file *fp; - int error = fget(dirp->fd, &fp); - if (error) { - return libc_error(error); - } + struct file *fp; + int error = fget(dirp->fd, &fp); + if (error) { + return libc_error(error); + } - long loc; - error = sys_telldir(fp, &loc); - fdrop(fp); - if (error) { - return libc_error(error); - } - return loc; + long loc; + error = sys_telldir(fp, &loc); + fdrop(fp); + if (error) { + return libc_error(error); + } + return loc; } void seekdir(DIR *dirp, long loc) { - struct file *fp; - int error = fget(dirp->fd, &fp); - if (error) { - // POSIX specifies seekdir() cannot return errors. - return; - } - sys_seekdir(fp, loc); - // Again, error code from sys_seekdir() is ignored. - fdrop(fp); + struct file *fp; + int error = fget(dirp->fd, &fp); + if (error) { + // POSIX specifies seekdir() cannot return errors. + return; + } + sys_seekdir(fp, loc); + // Again, error code from sys_seekdir() is ignored. + fdrop(fp); } TRACEPOINT(trace_vfs_mkdir, "\"%s\" 0%0o", const char*, mode_t); @@ -817,25 +817,25 @@ TRACEPOINT(trace_vfs_mkdir_err, "%d", int); int mkdir(const char *pathname, mode_t mode) { - struct task *t = main_task; - char path[PATH_MAX]; - int error; + struct task *t = main_task; + char path[PATH_MAX]; + int error; - mode = apply_umask(mode); + mode = apply_umask(mode); - trace_vfs_mkdir(pathname, mode); - if ((error = task_conv(t, pathname, VWRITE, path)) != 0) - goto out_errno; + trace_vfs_mkdir(pathname, mode); + if ((error = task_conv(t, pathname, VWRITE, path)) != 0) + goto out_errno; - error = sys_mkdir(path, mode); - if (error) - goto out_errno; - trace_vfs_mkdir_ret(); - return 0; - out_errno: - trace_vfs_mkdir_err(error); - errno = error; - return -1; + error = sys_mkdir(path, mode); + if (error) + goto out_errno; + trace_vfs_mkdir_ret(); + return 0; + out_errno: + trace_vfs_mkdir_err(error); + errno = error; + return -1; } TRACEPOINT(trace_vfs_rmdir, "\"%s\"", const char*); @@ -844,51 +844,51 @@ TRACEPOINT(trace_vfs_rmdir_err, "%d", int); int rmdir(const char *pathname) { - struct task *t = main_task; - char path[PATH_MAX]; - int error; + struct task *t = main_task; + char path[PATH_MAX]; + int error; - trace_vfs_rmdir(pathname); - error = ENOENT; - if (pathname == nullptr) - goto out_errno; - if ((error = task_conv(t, pathname, VWRITE, path)) != 0) - goto out_errno; + trace_vfs_rmdir(pathname); + error = ENOENT; + if (pathname == nullptr) + goto out_errno; + if ((error = task_conv(t, pathname, VWRITE, path)) != 0) + goto out_errno; - error = sys_rmdir(path); - if (error) - goto out_errno; - trace_vfs_rmdir_ret(); - return 0; - out_errno: - trace_vfs_rmdir_err(error); - errno = error; - return -1; + error = sys_rmdir(path); + if (error) + goto out_errno; + trace_vfs_rmdir_ret(); + return 0; + out_errno: + trace_vfs_rmdir_err(error); + errno = error; + return -1; } static void get_last_component(const char *path, char *dst) { - int pos = strlen(path) - 1; + int pos = strlen(path) - 1; - while (pos >= 0 && path[pos] == '/') - pos--; + while (pos >= 0 && path[pos] == '/') + pos--; - int component_end = pos; + int component_end = pos; - while (pos >= 0 && path[pos] != '/') - pos--; + while (pos >= 0 && path[pos] != '/') + pos--; - int component_start = pos + 1; + int component_start = pos + 1; - int len = component_end - component_start + 1; - memcpy(dst, path + component_start, len); - dst[len] = 0; + int len = component_end - component_start + 1; + memcpy(dst, path + component_start, len); + dst[len] = 0; } static bool null_or_empty(const char *str) { - return str == nullptr || *str == '\0'; + return str == nullptr || *str == '\0'; } TRACEPOINT(trace_vfs_rename, "\"%s\" \"%s\"", const char*, const char*); @@ -897,43 +897,43 @@ TRACEPOINT(trace_vfs_rename_err, "%d", int); int rename(const char *oldpath, const char *newpath) { - trace_vfs_rename(oldpath, newpath); - struct task *t = main_task; - char src[PATH_MAX]; - char dest[PATH_MAX]; - int error; - - error = ENOENT; - if (null_or_empty(oldpath) || null_or_empty(newpath)) - goto out_errno; - - get_last_component(oldpath, src); - if (!strcmp(src, ".") || !strcmp(src, "..")) { - error = EINVAL; - goto out_errno; - } - - get_last_component(newpath, dest); - if (!strcmp(dest, ".") || !strcmp(dest, "..")) { - error = EINVAL; - goto out_errno; - } - - if ((error = task_conv(t, oldpath, VREAD, src)) != 0) - goto out_errno; - - if ((error = task_conv(t, newpath, VWRITE, dest)) != 0) - goto out_errno; - - error = sys_rename(src, dest); - if (error) - goto out_errno; - trace_vfs_rename_ret(); - return 0; - out_errno: - trace_vfs_rename_err(error); - errno = error; - return -1; + trace_vfs_rename(oldpath, newpath); + struct task *t = main_task; + char src[PATH_MAX]; + char dest[PATH_MAX]; + int error; + + error = ENOENT; + if (null_or_empty(oldpath) || null_or_empty(newpath)) + goto out_errno; + + get_last_component(oldpath, src); + if (!strcmp(src, ".") || !strcmp(src, "..")) { + error = EINVAL; + goto out_errno; + } + + get_last_component(newpath, dest); + if (!strcmp(dest, ".") || !strcmp(dest, "..")) { + error = EINVAL; + goto out_errno; + } + + if ((error = task_conv(t, oldpath, VREAD, src)) != 0) + goto out_errno; + + if ((error = task_conv(t, newpath, VWRITE, dest)) != 0) + goto out_errno; + + error = sys_rename(src, dest); + if (error) + goto out_errno; + trace_vfs_rename_ret(); + return 0; + out_errno: + trace_vfs_rename_err(error); + errno = error; + return -1; } TRACEPOINT(trace_vfs_chdir, "\"%s\"", const char*); @@ -941,58 +941,58 @@ TRACEPOINT(trace_vfs_chdir_ret, ""); TRACEPOINT(trace_vfs_chdir_err, "%d", int); static int replace_cwd(struct task *t, struct file *new_cwdfp, - std::function<int (void)> chdir_func) + std::function<int (void)> chdir_func) { - struct file *old = nullptr; + struct file *old = nullptr; - if (!t) { - return 0; - } + if (!t) { + return 0; + } - if (t->t_cwdfp) { - old = t->t_cwdfp; - } + if (t->t_cwdfp) { + old = t->t_cwdfp; + } - /* Do the actual chdir operation here */ - int error = chdir_func(); + /* Do the actual chdir operation here */ + int error = chdir_func(); - t->t_cwdfp = new_cwdfp; - if (old) { - fdrop(old); - } + t->t_cwdfp = new_cwdfp; + if (old) { + fdrop(old); + } - return error; + return error; } int chdir(const char *pathname) { - trace_vfs_chdir(pathname); - struct task *t = main_task; - char path[PATH_MAX]; - struct file *fp; - int error; + trace_vfs_chdir(pathname); + struct task *t = main_task; + char path[PATH_MAX]; + struct file *fp; + int error; - error = ENOENT; - if (pathname == nullptr) - goto out_errno; + error = ENOENT; + if (pathname == nullptr) + goto out_errno; - if ((error = task_conv(t, pathname, VREAD, path)) != 0) - goto out_errno; + if ((error = task_conv(t, pathname, VREAD, path)) != 0) + goto out_errno; - /* Check if directory exits */ - error = sys_open(path, O_DIRECTORY, 0, &fp); - if (error) { - goto out_errno; - } + /* Check if directory exits */ + error = sys_open(path, O_DIRECTORY, 0, &fp); + if (error) { + goto out_errno; + } - replace_cwd(t, fp, [&]() { strlcpy(t->t_cwd, path, sizeof(t->t_cwd)); return 0; }); + replace_cwd(t, fp, [&]() { strlcpy(t->t_cwd, path, sizeof(t->t_cwd)); return 0; }); - trace_vfs_chdir_ret(); - return 0; - out_errno: - errno = error; - trace_vfs_chdir_err(errno); - return -1; + trace_vfs_chdir_ret(); + return 0; + out_errno: + errno = error; + trace_vfs_chdir_err(errno); + return -1; } TRACEPOINT(trace_vfs_fchdir, "%d", int); @@ -1001,28 +1001,28 @@ TRACEPOINT(trace_vfs_fchdir_err, "%d", int); int fchdir(int fd) { - trace_vfs_fchdir(fd); - struct task *t = main_task; - struct file *fp; - int error; + trace_vfs_fchdir(fd); + struct task *t = main_task; + struct file *fp; + int error; - error = fget(fd, &fp); - if (error) - goto out_errno; + error = fget(fd, &fp); + if (error) + goto out_errno; - error = replace_cwd(t, fp, [&]() { return sys_fchdir(fp, t->t_cwd); }); - if (error) { - fdrop(fp); - goto out_errno; - } + error = replace_cwd(t, fp, [&]() { return sys_fchdir(fp, t->t_cwd); }); + if (error) { + fdrop(fp); + goto out_errno; + } - trace_vfs_fchdir_ret(); - return 0; + trace_vfs_fchdir_ret(); + return 0; - out_errno: - trace_vfs_fchdir_err(error); - errno = error; - return -1; + out_errno: + trace_vfs_fchdir_err(error); + errno = error; + return -1; } TRACEPOINT(trace_vfs_link, "\"%s\" \"%s\"", const char*, const char*); @@ -1031,30 +1031,30 @@ TRACEPOINT(trace_vfs_link_err, "%d", int); int link(const char *oldpath, const char *newpath) { - struct task *t = main_task; - char path1[PATH_MAX]; - char path2[PATH_MAX]; - int error; + struct task *t = main_task; + char path1[PATH_MAX]; + char path2[PATH_MAX]; + int error; - trace_vfs_link(oldpath, newpath); + trace_vfs_link(oldpath, newpath); - error = ENOENT; - if (oldpath == nullptr || newpath == nullptr) - goto out_errno; - if ((error = task_conv(t, oldpath, VWRITE, path1)) != 0) - goto out_errno; - if ((error = task_conv(t, newpath, VWRITE, path2)) != 0) - goto out_errno; + error = ENOENT; + if (oldpath == nullptr || newpath == nullptr) + goto out_errno; + if ((error = task_conv(t, oldpath, VWRITE, path1)) != 0) + goto out_errno; + if ((error = task_conv(t, newpath, VWRITE, path2)) != 0) + goto out_errno; - error = sys_link(path1, path2); - if (error) - goto out_errno; - trace_vfs_link_ret(); - return 0; - out_errno: - trace_vfs_link_err(error); - errno = error; - return -1; + error = sys_link(path1, path2); + if (error) + goto out_errno; + trace_vfs_link_ret(); + return 0; + out_errno: + trace_vfs_link_err(error); + errno = error; + return -1; } @@ -1064,26 +1064,26 @@ TRACEPOINT(trace_vfs_symlink_err, "errno=%d", int); int symlink(const char *oldpath, const char *newpath) { - int error; + int error; - trace_vfs_symlink(oldpath, newpath); + trace_vfs_symlink(oldpath, newpath); - error = ENOENT; - if (oldpath == nullptr || newpath == nullptr) { - errno = ENOENT; - trace_vfs_symlink_err(error); - return (-1); - } + error = ENOENT; + if (oldpath == nullptr || newpath == nullptr) { + errno = ENOENT; + trace_vfs_symlink_err(error); + return (-1); + } - error = sys_symlink(oldpath, newpath); - if (error) { - errno = error; - trace_vfs_symlink_err(error); - return (-1); - } + error = sys_symlink(oldpath, newpath); + if (error) { + errno = error; + trace_vfs_symlink_err(error); + return (-1); + } - trace_vfs_symlink_ret(); - return 0; + trace_vfs_symlink_ret(); + return 0; } TRACEPOINT(trace_vfs_unlink, "\"%s\"", const char*); @@ -1092,26 +1092,26 @@ TRACEPOINT(trace_vfs_unlink_err, "%d", int); int unlink(const char *pathname) { - trace_vfs_unlink(pathname); - struct task *t = main_task; - char path[PATH_MAX]; - int error; + trace_vfs_unlink(pathname); + struct task *t = main_task; + char path[PATH_MAX]; + int error; - error = ENOENT; - if (pathname == nullptr) - goto out_errno; - if ((error = task_conv(t, pathname, VWRITE, path)) != 0) - goto out_errno; + error = ENOENT; + if (pathname == nullptr) + goto out_errno; + if ((error = task_conv(t, pathname, VWRITE, path)) != 0) + goto out_errno; - error = sys_unlink(path); - if (error) - goto out_errno; - trace_vfs_unlink_ret(); - return 0; - out_errno: - trace_vfs_unlink_err(error); - errno = error; - return -1; + error = sys_unlink(path); + if (error) + goto out_errno; + trace_vfs_unlink_ret(); + return 0; + out_errno: + trace_vfs_unlink_err(error); + errno = error; + return -1; } TRACEPOINT(trace_vfs_stat, "\"%s\" %p", const char*, struct stat*); @@ -1121,33 +1121,33 @@ TRACEPOINT(trace_vfs_stat_err, "%d", int); extern "C" int __xstat(int ver, const char *pathname, struct stat *st) { - struct task *t = main_task; - char path[PATH_MAX]; - int error; + struct task *t = main_task; + char path[PATH_MAX]; + int error; - trace_vfs_stat(pathname, st); + trace_vfs_stat(pathname, st); - error = task_conv(t, pathname, 0, path); - if (error) - goto out_errno; + error = task_conv(t, pathname, 0, path); + if (error) + goto out_errno; - error = sys_stat(path, st); - if (error) - goto out_errno; - trace_vfs_stat_ret(); - return 0; + error = sys_stat(path, st); + if (error) + goto out_errno; + trace_vfs_stat_ret(); + return 0; - out_errno: - trace_vfs_stat_err(error); - errno = error; - return -1; + out_errno: + trace_vfs_stat_err(error); + errno = error; + return -1; } LFS64(__xstat); int stat(const char *pathname, struct stat *st) { - return __xstat(1, pathname, st); + return __xstat(1, pathname, st); } LFS64(stat); @@ -1158,35 +1158,35 @@ TRACEPOINT(trace_vfs_lstat_err, "errno=%d", int); extern "C" int __lxstat(int ver, const char *pathname, struct stat *st) { - struct task *t = main_task; - char path[PATH_MAX]; - int error; + struct task *t = main_task; + char path[PATH_MAX]; + int error; - trace_vfs_lstat(pathname, st); + trace_vfs_lstat(pathname, st); - error = task_conv(t, pathname, 0, path); - if (error) { - errno = error; - trace_vfs_lstat_err(error); - return (-1); - } + error = task_conv(t, pathname, 0, path); + if (error) { + errno = error; + trace_vfs_lstat_err(error); + return (-1); + } - error = sys_lstat(path, st); - if (error) { - errno = error; - trace_vfs_lstat_err(error); - return (-1); - } + error = sys_lstat(path, st); + if (error) { + errno = error; + trace_vfs_lstat_err(error); + return (-1); + } - trace_vfs_lstat_ret(); - return 0; + trace_vfs_lstat_ret(); + return 0; } LFS64(__lxstat); int lstat(const char *pathname, struct stat *st) { - return __lxstat(1, pathname, st); + return __lxstat(1, pathname, st); } LFS64(lstat); @@ -1198,24 +1198,24 @@ TRACEPOINT(trace_vfs_statfs_err, "%d", int); extern "C" int __statfs(const char *pathname, struct statfs *buf) { - trace_vfs_statfs(pathname, buf); - struct task *t = main_task; - char path[PATH_MAX]; - int error; - - error = task_conv(t, pathname, 0, path); - if (error) - goto out_errno; - - error = sys_statfs(path, buf); - if (error) - goto out_errno; - trace_vfs_statfs_ret(); - return 0; - out_errno: - trace_vfs_statfs_err(error); - errno = error; - return -1; + trace_vfs_statfs(pathname, buf); + struct task *t = main_task; + char path[PATH_MAX]; + int error; + + error = task_conv(t, pathname, 0, path); + if (error) + goto out_errno; + + error = sys_statfs(path, buf); + if (error) + goto out_errno; + trace_vfs_statfs_ret(); + return 0; + out_errno: + trace_vfs_statfs_err(error); + errno = error; + return -1; } weak_alias(__statfs, statfs); @@ -1228,26 +1228,26 @@ TRACEPOINT(trace_vfs_fstatfs_err, "%d", int); extern "C" int __fstatfs(int fd, struct statfs *buf) { - struct file *fp; - int error; + struct file *fp; + int error; - trace_vfs_fstatfs(fd, buf); - error = fget(fd, &fp); - if (error) - goto out_errno; + trace_vfs_fstatfs(fd, buf); + error = fget(fd, &fp); + if (error) + goto out_errno; - error = sys_fstatfs(fp, buf); - fdrop(fp); + error = sys_fstatfs(fp, buf); + fdrop(fp); - if (error) - goto out_errno; - trace_vfs_fstatfs_ret(); - return 0; + if (error) + goto out_errno; + trace_vfs_fstatfs_ret(); + return 0; - out_errno: - trace_vfs_fstatfs_err(error); - errno = error; - return -1; + out_errno: + trace_vfs_fstatfs_err(error); + errno = error; + return -1; } weak_alias(__fstatfs, fstatfs); @@ -1256,28 +1256,28 @@ LFS64(fstatfs); static int statfs_to_statvfs(struct statvfs *dst, struct statfs *src) { - dst->f_bsize = src->f_bsize; - dst->f_frsize = src->f_bsize; - dst->f_blocks = src->f_blocks; - dst->f_bfree = src->f_bfree; - dst->f_bavail = src->f_bavail; - dst->f_files = src->f_files; - dst->f_ffree = src->f_ffree; - dst->f_favail = 0; - dst->f_fsid = src->f_fsid.__val[0]; - dst->f_flag = src->f_flags; - dst->f_namemax = src->f_namelen; - return 0; + dst->f_bsize = src->f_bsize; + dst->f_frsize = src->f_bsize; + dst->f_blocks = src->f_blocks; + dst->f_bfree = src->f_bfree; + dst->f_bavail = src->f_bavail; + dst->f_files = src->f_files; + dst->f_ffree = src->f_ffree; + dst->f_favail = 0; + dst->f_fsid = src->f_fsid.__val[0]; + dst->f_flag = src->f_flags; + dst->f_namemax = src->f_namelen; + return 0; } int statvfs(const char *pathname, struct statvfs *buf) { - struct statfs st; + struct statfs st; - if (__statfs(pathname, &st) < 0) - return -1; - return statfs_to_statvfs(buf, &st); + if (__statfs(pathname, &st) < 0) + return -1; + return statfs_to_statvfs(buf, &st); } LFS64(statvfs); @@ -1285,11 +1285,11 @@ LFS64(statvfs); int fstatvfs(int fd, struct statvfs *buf) { - struct statfs st; + struct statfs st; - if (__fstatfs(fd, &st) < 0) - return -1; - return statfs_to_statvfs(buf, &st); + if (__fstatfs(fd, &st) < 0) + return -1; + return statfs_to_statvfs(buf, &st); } LFS64(fstatvfs); @@ -1301,39 +1301,39 @@ TRACEPOINT(trace_vfs_getcwd_err, "%d", int); char *getcwd(char *path, size_t size) { - trace_vfs_getcwd(path, size); - struct task *t = main_task; - int len = strlen(t->t_cwd) + 1; - int error; - - if (!path) { - if (!size) - size = len; - path = (char*)malloc(size); - if (!path) { - error = ENOMEM; - goto out_errno; - } - } else { - if (!size) { - error = EINVAL; - goto out_errno; - } - } - - if (size < len) { - error = ERANGE; - goto out_errno; - } - - memcpy(path, t->t_cwd, len); - trace_vfs_getcwd_ret(path); - return path; - - out_errno: - trace_vfs_getcwd_err(error); - errno = error; - return nullptr; + trace_vfs_getcwd(path, size); + struct task *t = main_task; + int len = strlen(t->t_cwd) + 1; + int error; + + if (!path) { + if (!size) + size = len; + path = (char*)malloc(size); + if (!path) { + error = ENOMEM; + goto out_errno; + } + } else { + if (!size) { + error = EINVAL; + goto out_errno; + } + } + + if (size < len) { + error = ERANGE; + goto out_errno; + } + + memcpy(path, t->t_cwd, len); + trace_vfs_getcwd_ret(path); + return path; + + out_errno: + trace_vfs_getcwd_err(error); + errno = error; + return nullptr; } TRACEPOINT(trace_vfs_dup, "%d", int); @@ -1344,29 +1344,29 @@ TRACEPOINT(trace_vfs_dup_err, "%d", int); */ int dup(int oldfd) { - struct file *fp; - int newfd; - int error; + struct file *fp; + int newfd; + int error; - trace_vfs_dup(oldfd); - error = fget(oldfd, &fp); - if (error) - goto out_errno; + trace_vfs_dup(oldfd); + error = fget(oldfd, &fp); + if (error) + goto out_errno; - error = fdalloc(fp, &newfd); - if (error) - goto out_fdrop; + error = fdalloc(fp, &newfd); + if (error) + goto out_fdrop; - fdrop(fp); - trace_vfs_dup_ret(newfd); - return newfd; + fdrop(fp); + trace_vfs_dup_ret(newfd); + return newfd; - out_fdrop: - fdrop(fp); - out_errno: - trace_vfs_dup_err(error); - errno = error; - return -1; + out_fdrop: + fdrop(fp); + out_errno: + trace_vfs_dup_err(error); + errno = error; + return -1; } TRACEPOINT(trace_vfs_dup3, "%d %d 0x%x", int, int, int); @@ -1377,50 +1377,50 @@ TRACEPOINT(trace_vfs_dup3_err, "%d", int); */ int dup3(int oldfd, int newfd, int flags) { - struct file *fp; - int error; - - trace_vfs_dup3(oldfd, newfd, flags); - /* - * Don't allow any argument but O_CLOEXEC. But we even ignore - * that as we don't support exec() and thus don't care. - */ - if ((flags & ~O_CLOEXEC) != 0) { - error = EINVAL; - goto out_errno; - } + struct file *fp; + int error; + + trace_vfs_dup3(oldfd, newfd, flags); + /* + * Don't allow any argument but O_CLOEXEC. But we even ignore + * that as we don't support exec() and thus don't care. + */ + if ((flags & ~O_CLOEXEC) != 0) { + error = EINVAL; + goto out_errno; + } - if (oldfd == newfd) { - error = EINVAL; - goto out_errno; - } + if (oldfd == newfd) { + error = EINVAL; + goto out_errno; + } - error = fget(oldfd, &fp); - if (error) - goto out_errno; + error = fget(oldfd, &fp); + if (error) + goto out_errno; - error = fdset(newfd, fp); - if (error) { - fdrop(fp); - goto out_errno; - } + error = fdset(newfd, fp); + if (error) { + fdrop(fp); + goto out_errno; + } - fdrop(fp); - trace_vfs_dup3_ret(newfd); - return newfd; + fdrop(fp); + trace_vfs_dup3_ret(newfd); + return newfd; - out_errno: - trace_vfs_dup3_err(error); - errno = error; - return -1; + out_errno: + trace_vfs_dup3_err(error); + errno = error; + return -1; } int dup2(int oldfd, int newfd) { - if (oldfd == newfd) - return newfd; + if (oldfd == newfd) + return newfd; - return dup3(oldfd, newfd, 0); + return dup3(oldfd, newfd, 0); } /* @@ -1435,83 +1435,83 @@ TRACEPOINT(trace_vfs_fcntl_err, "%d", int); extern "C" int fcntl(int fd, int cmd, int arg) { - struct file *fp; - int ret = 0, error; - int tmp; - - trace_vfs_fcntl(fd, cmd, arg); - error = fget(fd, &fp); - if (error) - goto out_errno; - - // An important note about our handling of FD_CLOEXEC / O_CLOEXEC: - // close-on-exec shouldn't have been a file flag (fp->f_flags) - it is a - // file descriptor flag, meaning that that two dup()ed file descriptors - // could have different values for FD_CLOEXEC. Our current implementation - // *wrongly* makes close-on-exec an f_flag (using the bit O_CLOEXEC). - // There is little practical difference, though, because this flag is - // ignored in OSv anyway, as it doesn't support exec(). - switch (cmd) { - case F_DUPFD: - error = _fdalloc(fp, &ret, arg); - if (error) - goto out_errno; - break; - case F_GETFD: - ret = (fp->f_flags & O_CLOEXEC) ? FD_CLOEXEC : 0; - break; - case F_SETFD: - FD_LOCK(fp); - fp->f_flags = (fp->f_flags & ~O_CLOEXEC) | - ((arg & FD_CLOEXEC) ? O_CLOEXEC : 0); - FD_UNLOCK(fp); - break; - case F_GETFL: - // As explained above, the O_CLOEXEC should have been in f_flags, - // and shouldn't be returned. Linux always returns 0100000 ("the - // flag formerly known as O_LARGEFILE) so let's do it too. - ret = (oflags(fp->f_flags) & ~O_CLOEXEC) | 0100000; - break; - case F_SETFL: - FD_LOCK(fp); - fp->f_flags = fflags((oflags(fp->f_flags) & ~SETFL) | - (arg & SETFL)); - FD_UNLOCK(fp); - - /* Sync nonblocking/async state with file flags */ - tmp = fp->f_flags & FNONBLOCK; - fp->ioctl(FIONBIO, &tmp); - tmp = fp->f_flags & FASYNC; - fp->ioctl(FIOASYNC, &tmp); - - break; - case F_SETLK: - WARN_ONCE("fcntl(F_SETLK) stubbed\n"); - break; - case F_GETLK: - WARN_ONCE("fcntl(F_GETLK) stubbed\n"); - break; - case F_SETLKW: - WARN_ONCE("fcntl(F_SETLKW) stubbed\n"); - break; - case F_SETOWN: - WARN_ONCE("fcntl(F_SETOWN) stubbed\n"); - break; - default: - kprintf("unsupported fcntl cmd 0x%x\n", cmd); - error = EINVAL; - } - - fdrop(fp); - if (error) - goto out_errno; - trace_vfs_fcntl_ret(ret); - return ret; - - out_errno: - trace_vfs_fcntl_err(error); - errno = error; - return -1; + struct file *fp; + int ret = 0, error; + int tmp; + + trace_vfs_fcntl(fd, cmd, arg); + error = fget(fd, &fp); + if (error) + goto out_errno; + + // An important note about our handling of FD_CLOEXEC / O_CLOEXEC: + // close-on-exec shouldn't have been a file flag (fp->f_flags) - it is a + // file descriptor flag, meaning that that two dup()ed file descriptors + // could have different values for FD_CLOEXEC. Our current implementation + // *wrongly* makes close-on-exec an f_flag (using the bit O_CLOEXEC). + // There is little practical difference, though, because this flag is + // ignored in OSv anyway, as it doesn't support exec(). + switch (cmd) { + case F_DUPFD: + error = _fdalloc(fp, &ret, arg); + if (error) + goto out_errno; + break; + case F_GETFD: + ret = (fp->f_flags & O_CLOEXEC) ? FD_CLOEXEC : 0; + break; + case F_SETFD: + FD_LOCK(fp); + fp->f_flags = (fp->f_flags & ~O_CLOEXEC) | + ((arg & FD_CLOEXEC) ? O_CLOEXEC : 0); + FD_UNLOCK(fp); + break; + case F_GETFL: + // As explained above, the O_CLOEXEC should have been in f_flags, + // and shouldn't be returned. Linux always returns 0100000 ("the + // flag formerly known as O_LARGEFILE) so let's do it too. + ret = (oflags(fp->f_flags) & ~O_CLOEXEC) | 0100000; + break; + case F_SETFL: + FD_LOCK(fp); + fp->f_flags = fflags((oflags(fp->f_flags) & ~SETFL) | + (arg & SETFL)); + FD_UNLOCK(fp); + + /* Sync nonblocking/async state with file flags */ + tmp = fp->f_flags & FNONBLOCK; + fp->ioctl(FIONBIO, &tmp); + tmp = fp->f_flags & FASYNC; + fp->ioctl(FIOASYNC, &tmp); + + break; + case F_SETLK: + WARN_ONCE("fcntl(F_SETLK) stubbed\n"); + break; + case F_GETLK: + WARN_ONCE("fcntl(F_GETLK) stubbed\n"); + break; + case F_SETLKW: + WARN_ONCE("fcntl(F_SETLKW) stubbed\n"); + break; + case F_SETOWN: + WARN_ONCE("fcntl(F_SETOWN) stubbed\n"); + break; + default: + kprintf("unsupported fcntl cmd 0x%x\n", cmd); + error = EINVAL; + } + + fdrop(fp); + if (error) + goto out_errno; + trace_vfs_fcntl_ret(ret); + return ret; + + out_errno: + trace_vfs_fcntl_err(error); + errno = error; + return -1; } TRACEPOINT(trace_vfs_access, "\"%s\" 0%0o", const char*, int); @@ -1523,72 +1523,72 @@ TRACEPOINT(trace_vfs_access_err, "%d", int); */ int access(const char *pathname, int mode) { - trace_vfs_access(pathname, mode); - struct task *t = main_task; - char path[PATH_MAX]; - int acc, error = 0; + trace_vfs_access(pathname, mode); + struct task *t = main_task; + char path[PATH_MAX]; + int acc, error = 0; - acc = 0; - if (mode & R_OK) - acc |= VREAD; - if (mode & W_OK) - acc |= VWRITE; + acc = 0; + if (mode & R_OK) + acc |= VREAD; + if (mode & W_OK) + acc |= VWRITE; - if ((error = task_conv(t, pathname, acc, path)) != 0) - goto out_errno; + if ((error = task_conv(t, pathname, acc, path)) != 0) + goto out_errno; - error = sys_access(path, mode); - if (error) - goto out_errno; - trace_vfs_access_ret(); - return 0; - out_errno: - errno = error; - trace_vfs_access_err(error); - return -1; + error = sys_access(path, mode); + if (error) + goto out_errno; + trace_vfs_access_ret(); + return 0; + out_errno: + errno = error; + trace_vfs_access_err(error); + return -1; } int faccessat(int dirfd, const char *pathname, int mode, int flags) { - if (flags & AT_SYMLINK_NOFOLLOW) { - UNIMPLEMENTED("faccessat() with AT_SYMLINK_NOFOLLOW"); - } + if (flags & AT_SYMLINK_NOFOLLOW) { + UNIMPLEMENTED("faccessat() with AT_SYMLINK_NOFOLLOW"); + } - if (pathname[0] == '/' || dirfd == AT_FDCWD) { - return access(pathname, mode); - } + if (pathname[0] == '/' || dirfd == AT_FDCWD) { + return access(pathname, mode); + } - struct file *fp; - int error = fget(dirfd, &fp); - if (error) { - errno = error; - return -1; - } + struct file *fp; + int error = fget(dirfd, &fp); + if (error) { + errno = error; + return -1; + } - struct vnode *vp = fp->f_dentry->d_vnode; - vn_lock(vp); + struct vnode *vp = fp->f_dentry->d_vnode; + vn_lock(vp); - std::unique_ptr<char []> up (new char[PATH_MAX]); - char *p = up.get(); + std::unique_ptr<char []> up (new char[PATH_MAX]); + char *p = up.get(); - /* build absolute path */ - strlcpy(p, fp->f_dentry->d_mount->m_path, PATH_MAX); - strlcat(p, fp->f_dentry->d_path, PATH_MAX); - strlcat(p, "/", PATH_MAX); - strlcat(p, pathname, PATH_MAX); + /* build absolute path */ + strlcpy(p, fp->f_dentry->d_mount->m_path, PATH_MAX); + strlcat(p, fp->f_dentry->d_path, PATH_MAX); + strlcat(p, "/", PATH_MAX); + strlcat(p, pathname, PATH_MAX); - error = access(p, mode); + error = access(p, mode); - vn_unlock(vp); - fdrop(fp); + vn_unlock(vp); + fdrop(fp); - return error; + return error; } extern "C" int euidaccess(const char *pathname, int mode) { - return access(pathname, mode); + return access(pathname, mode); } weak_alias(euidaccess,eaccess); @@ -1598,42 +1598,42 @@ static int fs_pipe(struct task *t, struct msg *msg) { #ifdef CONFIG_FIFOFS - char path[PATH_MAX]; - file_t rfp, wfp; - int error, rfd, wfd; - - DPRINTF(VFSDB_CORE, ("fs_pipe\n")); - - if ((rfd = task_newfd(t)) == -1) - return EMFILE; - t->t_ofile[rfd] = (file_t)1; /* temp */ - - if ((wfd = task_newfd(t)) == -1) { - t->t_ofile[rfd] = nullptr; - return EMFILE; - } - sprintf(path, "/mnt/fifo/pipe-%x-%d", (u_int)t->t_taskid, rfd); - - if ((error = sys_mknod(path, S_IFIFO)) != 0) - goto out; - if ((error = sys_open(path, O_RDONLY | O_NONBLOCK, 0, &rfp)) != 0) { - goto out; - } - if ((error = sys_open(path, O_WRONLY | O_NONBLOCK, 0, &wfp)) != 0) { - goto out; - } - t->t_ofile[rfd] = rfp; - t->t_ofile[wfd] = wfp; - t->t_nopens += 2; - msg->data[0] = rfd; - msg->data[1] = wfd; - return 0; - out: - t->t_ofile[rfd] = nullptr; - t->t_ofile[wfd] = nullptr; - return error; + char path[PATH_MAX]; + file_t rfp, wfp; + int error, rfd, wfd; + + DPRINTF(VFSDB_CORE, ("fs_pipe\n")); + + if ((rfd = task_newfd(t)) == -1) + return EMFILE; + t->t_ofile[rfd] = (file_t)1; /* temp */ + + if ((wfd = task_newfd(t)) == -1) { + t->t_ofile[rfd] = nullptr; + return EMFILE; + } + sprintf(path, "/mnt/fifo/pipe-%x-%d", (u_int)t->t_taskid, rfd); + + if ((error = sys_mknod(path, S_IFIFO)) != 0) + goto out; + if ((error = sys_open(path, O_RDONLY | O_NONBLOCK, 0, &rfp)) != 0) { + goto out; + } + if ((error = sys_open(path, O_WRONLY | O_NONBLOCK, 0, &wfp)) != 0) { + goto out; + } + t->t_ofile[rfd] = rfp; + t->t_ofile[wfd] = wfp; + t->t_nopens += 2; + msg->data[0] = rfd; + msg->data[1] = wfd; + return 0; + out: + t->t_ofile[rfd] = nullptr; + t->t_ofile[wfd] = nullptr; + return error; #else - return ENOSYS; + return ENOSYS; #endif } #endif @@ -1647,25 +1647,25 @@ TRACEPOINT(trace_vfs_isatty_err, "%d", int); */ int isatty(int fd) { - struct file *fp; - int istty = 0; + struct file *fp; + int istty = 0; - trace_vfs_isatty(fd); - fileref f(fileref_from_fd(fd)); - if (!f) { - errno = EBADF; - trace_vfs_isatty_err(errno); - return -1; - } + trace_vfs_isatty(fd); + fileref f(fileref_from_fd(fd)); + if (!f) { + errno = EBADF; + trace_vfs_isatty_err(errno); + return -1; + } - fp = f.get(); - if (dynamic_cast<tty_file*>(fp) || - (fp->f_dentry && fp->f_dentry->d_vnode->v_flags & VISTTY)) { - istty = 1; - } + fp = f.get(); + if (dynamic_cast<tty_file*>(fp) || + (fp->f_dentry && fp->f_dentry->d_vnode->v_flags & VISTTY)) { + istty = 1; + } - trace_vfs_isatty_ret(istty); - return istty; + trace_vfs_isatty_ret(istty); + return istty; } TRACEPOINT(trace_vfs_truncate, "\"%s\" 0x%x", const char*, off_t); @@ -1674,26 +1674,26 @@ TRACEPOINT(trace_vfs_truncate_err, "%d", int); int truncate(const char *pathname, off_t length) { - trace_vfs_truncate(pathname, length); - struct task *t = main_task; - char path[PATH_MAX]; - int error; + trace_vfs_truncate(pathname, length); + struct task *t = main_task; + char path[PATH_MAX]; + int error; - error = ENOENT; - if (pathname == nullptr) - goto out_errno; - if ((error = task_conv(t, pathname, VWRITE, path)) != 0) - goto out_errno; + error = ENOENT; + if (pathname == nullptr) + goto out_errno; + if ((error = task_conv(t, pathname, VWRITE, path)) != 0) + goto out_errno; - error = sys_truncate(path, length); - if (error) - goto out_errno; - trace_vfs_truncate_ret(); - return 0; - out_errno: - errno = error; - trace_vfs_truncate_err(error); - return -1; + error = sys_truncate(path, length); + if (error) + goto out_errno; + trace_vfs_truncate_ret(); + return 0; + out_errno: + errno = error; + trace_vfs_truncate_err(error); + return -1; } LFS64(truncate); @@ -1704,58 +1704,58 @@ TRACEPOINT(trace_vfs_ftruncate_err, "%d", int); int ftruncate(int fd, off_t length) { - trace_vfs_ftruncate(fd, length); - struct file *fp; - int error; + trace_vfs_ftruncate(fd, length); + struct file *fp; + int error; - error = fget(fd, &fp); - if (error) - goto out_errno; + error = fget(fd, &fp); + if (error) + goto out_errno; - error = sys_ftruncate(fp, length); - fdrop(fp); + error = sys_ftruncate(fp, length); + fdrop(fp); - if (error) - goto out_errno; - trace_vfs_ftruncate_ret(); - return 0; + if (error) + goto out_errno; + trace_vfs_ftruncate_ret(); + return 0; - out_errno: - errno = error; - trace_vfs_ftruncate_err(error); - return -1; + out_errno: + errno = error; + trace_vfs_ftruncate_err(error); + return -1; } LFS64(ftruncate); ssize_t readlink(const char *pathname, char *buf, size_t bufsize) { - struct task *t = main_task; - char path[PATH_MAX]; - int error; - ssize_t size; + struct task *t = main_task; + char path[PATH_MAX]; + int error; + ssize_t size; - error = -EINVAL; - if (bufsize <= 0) - goto out_errno; + error = -EINVAL; + if (bufsize <= 0) + goto out_errno; - error = ENOENT; - if (pathname == nullptr) - goto out_errno; - error = task_conv(t, pathname, VWRITE, path); - if (error) - goto out_errno; + error = ENOENT; + if (pathname == nullptr) + goto out_errno; + error = task_conv(t, pathname, VWRITE, path); + if (error) + goto out_errno; - size = 0; - error = sys_readlink(path, buf, bufsize, &size); + size = 0; + error = sys_readlink(path, buf, bufsize, &size); - if (error != 0) - goto out_errno; + if (error != 0) + goto out_errno; - return size; - out_errno: - errno = error; - return -1; + return size; + out_errno: + errno = error; + return -1; } TRACEPOINT(trace_vfs_fallocate, "%d %d 0x%x 0x%x", int, int, loff_t, loff_t); @@ -1764,26 +1764,26 @@ TRACEPOINT(trace_vfs_fallocate_err, "%d", int); int fallocate(int fd, int mode, loff_t offset, loff_t len) { - struct file *fp; - int error; + struct file *fp; + int error; - trace_vfs_fallocate(fd, mode, offset, len); - error = fget(fd, &fp); - if (error) - goto out_errno; + trace_vfs_fallocate(fd, mode, offset, len); + error = fget(fd, &fp); + if (error) + goto out_errno; - error = sys_fallocate(fp, mode, offset, len); - fdrop(fp); + error = sys_fallocate(fp, mode, offset, len); + fdrop(fp); - if (error) - goto out_errno; - trace_vfs_fallocate_ret(); - return 0; + if (error) + goto out_errno; + trace_vfs_fallocate_ret(); + return 0; - out_errno: - trace_vfs_fallocate_err(error); - errno = error; - return -1; + out_errno: + trace_vfs_fallocate_err(error); + errno = error; + return -1; } LFS64(fallocate); @@ -1794,60 +1794,60 @@ TRACEPOINT(trace_vfs_utimes_err, "%d", int); int futimes(int fd, const struct timeval times[2]) { - return futimesat(fd, nullptr, times); + return futimesat(fd, nullptr, times); } int futimesat(int dirfd, const char *pathname, const struct timeval times[2]) { - struct stat st; - struct file *fp; - int error; - char *absolute_path; - - if ((pathname && pathname[0] == '/') || dirfd == AT_FDCWD) - return utimes(pathname, times); - - // Note: if pathname == nullptr, futimesat operates on dirfd itself, and in - // that case it doesn't have to be a directory. - if (pathname) { - error = fstat(dirfd, &st); - if (error) { - error = errno; - goto out_errno; - } - - if (!S_ISDIR(st.st_mode)){ - error = ENOTDIR; - goto out_errno; - } - } + struct stat st; + struct file *fp; + int error; + char *absolute_path; + + if ((pathname && pathname[0] == '/') || dirfd == AT_FDCWD) + return utimes(pathname, times); + + // Note: if pathname == nullptr, futimesat operates on dirfd itself, and in + // that case it doesn't have to be a directory. + if (pathname) { + error = fstat(dirfd, &st); + if (error) { + error = errno; + goto out_errno; + } + + if (!S_ISDIR(st.st_mode)){ + error = ENOTDIR; + goto out_errno; + } + } - error = fget(dirfd, &fp); - if (error) - goto out_errno; + error = fget(dirfd, &fp); + if (error) + goto out_errno; - /* build absolute path */ - absolute_path = (char*)malloc(PATH_MAX); - strlcpy(absolute_path, fp->f_dentry->d_mount->m_path, PATH_MAX); - strlcat(absolute_path, fp->f_dentry->d_path, PATH_MAX); + /* build absolute path */ + absolute_path = (char*)malloc(PATH_MAX); + strlcpy(absolute_path, fp->f_dentry->d_mount->m_path, PATH_MAX); + strlcat(absolute_path, fp->f_dentry->d_path, PATH_MAX); - if (pathname) { - strlcat(absolute_path, "/", PATH_MAX); - strlcat(absolute_path, pathname, PATH_MAX); - } + if (pathname) { + strlcat(absolute_path, "/", PATH_MAX); + strlcat(absolute_path, pathname, PATH_MAX); + } - error = utimes(absolute_path, times); - free(absolute_path); + error = utimes(absolute_path, times); + free(absolute_path); - fdrop(fp); + fdrop(fp); - if (error) - goto out_errno; - return 0; + if (error) + goto out_errno; + return 0; - out_errno: - errno = error; - return -1; + out_errno: + errno = error; + return -1; } TRACEPOINT(trace_vfs_utimensat, "\"%s\"", const char*); @@ -1857,17 +1857,17 @@ TRACEPOINT(trace_vfs_utimensat_err, "%d", int); extern "C" int utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags) { - trace_vfs_utimensat(pathname); + trace_vfs_utimensat(pathname); - auto error = sys_utimensat(dirfd, pathname, times, flags); - if (error) { - trace_vfs_utimensat_err(error); - errno = error; - return -1; - } + auto error = sys_utimensat(dirfd, pathname, times, flags); + if (error) { + trace_vfs_utimensat_err(error); + errno = error; + return -1; + } - trace_vfs_utimensat_ret(); - return 0; + trace_vfs_utimensat_ret(); + return 0; } TRACEPOINT(trace_vfs_futimens, "%d", int); @@ -1877,73 +1877,73 @@ TRACEPOINT(trace_vfs_futimens_err, "%d", int); extern "C" int futimens(int fd, const struct timespec times[2]) { - trace_vfs_futimens(fd); + trace_vfs_futimens(fd); - auto error = sys_futimens(fd, times); - if (error) { - trace_vfs_futimens_err(error); - errno = error; - return -1; - } + auto error = sys_futimens(fd, times); + if (error) { + trace_vfs_futimens_err(error); + errno = error; + return -1; + } - trace_vfs_futimens_ret(); - return 0; + trace_vfs_futimens_ret(); + return 0; } static int do_utimes(const char *pathname, const struct timeval times[2], int flags) { - struct task *t = main_task; - char path[PATH_MAX]; - int error; + struct task *t = main_task; + char path[PATH_MAX]; + int error; - trace_vfs_utimes(pathname); + trace_vfs_utimes(pathname); - error = task_conv(t, pathname, 0, path); - if (error) { - trace_vfs_utimes_err(error); - return libc_error(error); - } + error = task_conv(t, pathname, 0, path); + if (error) { + trace_vfs_utimes_err(error); + return libc_error(error); + } - error = sys_utimes(path, times, flags); - if (error) { - trace_vfs_utimes_err(error); - return libc_error(error); - } + error = sys_utimes(path, times, flags); + if (error) { + trace_vfs_utimes_err(error); + return libc_error(error); + } - trace_vfs_utimes_ret(); - return 0; + trace_vfs_utimes_ret(); + return 0; } extern "C" int utimes(const char *pathname, const struct timeval times[2]) { - return do_utimes(pathname, times, 0); + return do_utimes(pathname, times, 0); } extern "C" int lutimes(const char *pathname, const struct timeval times[2]) { - return do_utimes(pathname, times, AT_SYMLINK_NOFOLLOW); + return do_utimes(pathname, times, AT_SYMLINK_NOFOLLOW); } extern "C" int utime(const char *pathname, const struct utimbuf *t) { - using namespace std::chrono; - - struct timeval times[2]; - times[0].tv_usec = 0; - times[1].tv_usec = 0; - if (!t) { - long int tsec = duration_cast<seconds>(osv::clock::wall::now().time_since_epoch()).count(); - times[0].tv_sec = tsec; - times[1].tv_sec = tsec; - } else { - times[0].tv_sec = t->actime; - times[1].tv_sec = t->modtime; - } + using namespace std::chrono; + + struct timeval times[2]; + times[0].tv_usec = 0; + times[1].tv_usec = 0; + if (!t) { + long int tsec = duration_cast<seconds>(osv::clock::wall::now().time_since_epoch()).count(); + times[0].tv_sec = tsec; + times[1].tv_sec = tsec; + } else { + times[0].tv_sec = t->actime; + times[1].tv_sec = t->modtime; + } - return utimes(pathname, times); + return utimes(pathname, times); } TRACEPOINT(trace_vfs_chmod, "\"%s\" 0%0o", const char*, mode_t); @@ -1952,23 +1952,23 @@ TRACEPOINT(trace_vfs_chmod_err, "%d", int); int chmod(const char *pathname, mode_t mode) { - trace_vfs_chmod(pathname, mode); - struct task *t = main_task; - char path[PATH_MAX]; - int error = ENOENT; - if (pathname == nullptr) - goto out_errno; - if ((error = task_conv(t, pathname, VWRITE, path)) != 0) - goto out_errno; - error = sys_chmod(path, mode & ALLPERMS); - if (error) - goto out_errno; - trace_vfs_chmod_ret(); - return 0; + trace_vfs_chmod(pathname, mode); + struct task *t = main_task; + char path[PATH_MAX]; + int error = ENOENT; + if (pathname == nullptr) + goto out_errno; + if ((error = task_conv(t, pathname, VWRITE, path)) != 0) + goto out_errno; + error = sys_chmod(path, mode & ALLPERMS); + if (error) + goto out_errno; + trace_vfs_chmod_ret(); + return 0; out_errno: - trace_vfs_chmod_err(error); - errno = error; - return -1; + trace_vfs_chmod_err(error); + errno = error; + return -1; } TRACEPOINT(trace_vfs_fchmod, "\"%d\" 0%0o", int, mode_t); @@ -1976,15 +1976,15 @@ TRACEPOINT(trace_vfs_fchmod_ret, ""); int fchmod(int fd, mode_t mode) { - trace_vfs_fchmod(fd, mode); - auto error = sys_fchmod(fd, mode & ALLPERMS); - trace_vfs_fchmod_ret(); - if (error) { - errno = error; - return -1; - } else { - return 0; - } + trace_vfs_fchmod(fd, mode); + auto error = sys_fchmod(fd, mode & ALLPERMS); + trace_vfs_fchmod_ret(); + if (error) { + errno = error; + return -1; + } else { + return 0; + } } TRACEPOINT(trace_vfs_fchown, "\"%d\" %d %d", int, uid_t, gid_t); @@ -1992,101 +1992,101 @@ TRACEPOINT(trace_vfs_fchown_ret, ""); int fchown(int fd, uid_t owner, gid_t group) { - trace_vfs_fchown(fd, owner, group); - WARN_STUBBED(); - trace_vfs_fchown_ret(); - return 0; + trace_vfs_fchown(fd, owner, group); + WARN_STUBBED(); + trace_vfs_fchown_ret(); + return 0; } int chown(const char *path, uid_t owner, gid_t group) { - WARN_STUBBED(); - return 0; + WARN_STUBBED(); + return 0; } int lchown(const char *path, uid_t owner, gid_t group) { - WARN_STUBBED(); - return 0; + WARN_STUBBED(); + return 0; } ssize_t sendfile(int out_fd, int in_fd, off_t *_offset, size_t count) { - struct file *in_fp; - struct file *out_fp; - fileref in_f{fileref_from_fd(in_fd)}; - fileref out_f{fileref_from_fd(out_fd)}; + struct file *in_fp; + struct file *out_fp; + fileref in_f{fileref_from_fd(in_fd)}; + fileref out_f{fileref_from_fd(out_fd)}; - if (!in_f || !out_f) { - return libc_error(EBADF); - } + if (!in_f || !out_f) { + return libc_error(EBADF); + } - in_fp = in_f.get(); - out_fp = out_f.get(); + in_fp = in_f.get(); + out_fp = out_f.get(); - if (!in_fp->f_dentry) { - return libc_error(EBADF); - } + if (!in_fp->f_dentry) { + return libc_error(EBADF); + } - if (!(in_fp->f_flags & FREAD)) { - return libc_error(EBADF); - } + if (!(in_fp->f_flags & FREAD)) { + return libc_error(EBADF); + } - if (out_fp->f_type & DTYPE_VNODE) { - if (!out_fp->f_dentry) { - return libc_error(EBADF); + if (out_fp->f_type & DTYPE_VNODE) { + if (!out_fp->f_dentry) { + return libc_error(EBADF); } else if (!(out_fp->f_flags & FWRITE)) { - return libc_error(EBADF); + return libc_error(EBADF); + } } - } - off_t offset ; + off_t offset ; - if (_offset != nullptr) { - offset = *_offset; - } else { - /* if _offset is nullptr, we need to read from the present position of in_fd */ - offset = lseek(in_fd, 0, SEEK_CUR); - } + if (_offset != nullptr) { + offset = *_offset; + } else { + /* if _offset is nullptr, we need to read from the present position of in_fd */ + offset = lseek(in_fd, 0, SEEK_CUR); + } - // Constrain count to the extent of the file... - struct stat st; - if (fstat(in_fd, &st) < 0) { - return -1; - } else { - if (offset >= st.st_size) { - return 0; - } else if ((offset + count) >= st.st_size) { - count = st.st_size - offset; - if (count == 0) { - return 0; - } - } - } + // Constrain count to the extent of the file... + struct stat st; + if (fstat(in_fd, &st) < 0) { + return -1; + } else { + if (offset >= st.st_size) { + return 0; + } else if ((offset + count) >= st.st_size) { + count = st.st_size - offset; + if (count == 0) { + return 0; + } + } + } - size_t bytes_to_mmap = count + (offset % mmu::page_size); - off_t offset_for_mmap = align_down(offset, (off_t)mmu::page_size); + size_t bytes_to_mmap = count + (offset % mmu::page_size); + off_t offset_for_mmap = align_down(offset, (off_t)mmu::page_size); - char *src = static_cast<char *>(mmap(nullptr, bytes_to_mmap, PROT_READ, MAP_SHARED, in_fd, offset_for_mmap)); + char *src = static_cast<char *>(mmap(nullptr, bytes_to_mmap, PROT_READ, MAP_SHARED, in_fd, offset_for_mmap)); - if (src == MAP_FAILED) { - return -1; - } + if (src == MAP_FAILED) { + return -1; + } - auto ret = write(out_fd, src + (offset % PAGESIZE), count); + auto ret = write(out_fd, src + (offset % PAGESIZE), count); - if (ret < 0) { - return libc_error(errno); - } else if(_offset == nullptr) { - lseek(in_fd, ret, SEEK_CUR); - } else { - *_offset += ret; - } + if (ret < 0) { + return libc_error(errno); + } else if(_offset == nullptr) { + lseek(in_fd, ret, SEEK_CUR); + } else { + *_offset += ret; + } - assert(munmap(src, count) == 0); + assert(munmap(src, count) == 0); - return ret; + return ret; } #undef sendfile64 @@ -2096,20 +2096,20 @@ NO_SYS(int fchmodat(int dirfd, const char *pathname, mode_t mode, int flags)); mode_t umask(mode_t newmask) { - return global_umask.exchange(newmask, std::memory_order_relaxed); + return global_umask.exchange(newmask, std::memory_order_relaxed); } int fs_noop(void) { - return 0; + return 0; } int chroot(const char *path) { - WARN_STUBBED(); - errno = ENOSYS; - return -1; + WARN_STUBBED(); + errno = ENOSYS; + return -1; } // unpack_bootfs() unpacks a collection of files stored as part of the OSv @@ -2120,14 +2120,14 @@ int chroot(const char *path) #define BOOTFS_PATH_MAX 111 enum class bootfs_file_type : char { other = 0, symlink = 1 }; struct bootfs_metadata { - uint64_t size; - uint64_t offset; - // The file's type. Can be "symlink" or "other". A directory is an "other" - // file with its name ending with a "/" (and no content). - bootfs_file_type type; - // name must end with a null. For symlink files, the content must end - // with a null as well. - char name[BOOTFS_PATH_MAX]; + uint64_t size; + uint64_t offset; + // The file's type. Can be "symlink" or "other". A directory is an "other" + // file with its name ending with a "/" (and no content). + bootfs_file_type type; + // name must end with a null. For symlink files, the content must end + // with a null as well. + char name[BOOTFS_PATH_MAX]; }; extern char bootfs_start; @@ -2135,225 +2135,225 @@ extern char bootfs_start; int ramfs_set_file_data(struct vnode *vp, const void *data, size_t size); void unpack_bootfs(void) { - struct bootfs_metadata *md = (struct bootfs_metadata *)&bootfs_start; - int fd, i; - - for (i = 0; md[i].name[0]; i++) { - int ret; - char *p; - - // mkdir() directories needed for this path name, as necessary - char tmp[BOOTFS_PATH_MAX]; - strlcpy(tmp, md[i].name, BOOTFS_PATH_MAX); - for (p = tmp; *p; ++p) { - if (*p == '/') { - *p = '\0'; - mkdir(tmp, 0666); // silently ignore errors and existing dirs - *p = '/'; - } - } - - if (md[i].type == bootfs_file_type::symlink) { - // This is a symbolic link record. The file's content is the - // target path, and we assume ends with a null. - if (symlink(&bootfs_start + md[i].offset, md[i].name) != 0) { - kprintf("couldn't symlink %s: %d\n", md[i].name, errno); - sys_panic("unpack_bootfs failed"); - } - continue; - } - if (*(p-1) == '/' && md[i].size == 0) { - // This is directory record. Nothing else to do - continue; - } - - fd = creat(md[i].name, 0666); - if (fd < 0) { - kprintf("couldn't create %s: %d\n", - md[i].name, errno); - sys_panic("unpack_bootfs failed"); - } - - struct file *fp; - int error = fget(fd, &fp); - if (error) { - kprintf("couldn't fget %s: %d\n", - md[i].name, error); - sys_panic("unpack_bootfs failed"); - } - - struct vnode *vp = fp->f_dentry->d_vnode; - ret = ramfs_set_file_data(vp, &bootfs_start + md[i].offset, md[i].size); - if (ret) { - kprintf("ramfs_set_file_data failed, ret = %d\n", ret); - sys_panic("unpack_bootfs failed"); - } - - fdrop(fp); - close(fd); - } + struct bootfs_metadata *md = (struct bootfs_metadata *)&bootfs_start; + int fd, i; + + for (i = 0; md[i].name[0]; i++) { + int ret; + char *p; + + // mkdir() directories needed for this path name, as necessary + char tmp[BOOTFS_PATH_MAX]; + strlcpy(tmp, md[i].name, BOOTFS_PATH_MAX); + for (p = tmp; *p; ++p) { + if (*p == '/') { + *p = '\0'; + mkdir(tmp, 0666); // silently ignore errors and existing dirs + *p = '/'; + } + } + + if (md[i].type == bootfs_file_type::symlink) { + // This is a symbolic link record. The file's content is the + // target path, and we assume ends with a null. + if (symlink(&bootfs_start + md[i].offset, md[i].name) != 0) { + kprintf("couldn't symlink %s: %d\n", md[i].name, errno); + sys_panic("unpack_bootfs failed"); + } + continue; + } + if (*(p-1) == '/' && md[i].size == 0) { + // This is directory record. Nothing else to do + continue; + } + + fd = creat(md[i].name, 0666); + if (fd < 0) { + kprintf("couldn't create %s: %d\n", + md[i].name, errno); + sys_panic("unpack_bootfs failed"); + } + + struct file *fp; + int error = fget(fd, &fp); + if (error) { + kprintf("couldn't fget %s: %d\n", + md[i].name, error); + sys_panic("unpack_bootfs failed"); + } + + struct vnode *vp = fp->f_dentry->d_vnode; + ret = ramfs_set_file_data(vp, &bootfs_start + md[i].offset, md[i].size); + if (ret) { + kprintf("ramfs_set_file_data failed, ret = %d\n", ret); + sys_panic("unpack_bootfs failed"); + } + + fdrop(fp); + close(fd); + } } void mount_rootfs(void) { - int ret; + int ret; - ret = sys_mount("", "/", "ramfs", 0, nullptr); - if (ret) - kprintf("failed to mount rootfs, error = %s\n", strerror(ret)); + ret = sys_mount("", "/", "ramfs", 0, nullptr); + if (ret) + kprintf("failed to mount rootfs, error = %s\n", strerror(ret)); - if (mkdir("/dev", 0755) < 0) - kprintf("failed to create /dev, error = %s\n", strerror(errno)); + if (mkdir("/dev", 0755) < 0) + kprintf("failed to create /dev, error = %s\n", strerror(errno)); - ret = sys_mount("", "/dev", "devfs", 0, nullptr); - if (ret) - kprintf("failed to mount devfs, error = %s\n", strerror(ret)); + ret = sys_mount("", "/dev", "devfs", 0, nullptr); + if (ret) + kprintf("failed to mount devfs, error = %s\n", strerror(ret)); } extern "C" int nmount(struct iovec *iov, unsigned niov, int flags) { - struct args { - char* fstype = nullptr; - char* fspath = nullptr; - char* from = nullptr; - }; - static unordered_map<string, char* args::*> argmap { - { "fstype", &args::fstype }, - { "fspath", &args::fspath }, - { "from", &args::from }, - }; - args a; - for (size_t i = 0; i < niov; i += 2) { - std::string s(static_cast<const char*>(iov[i].iov_base)); - if (argmap.count(s)) { - a.*(argmap[s]) = static_cast<char*>(iov[i+1].iov_base); - } - } - return sys_mount(a.from, a.fspath, a.fstype, flags, nullptr); + struct args { + char* fstype = nullptr; + char* fspath = nullptr; + char* from = nullptr; + }; + static unordered_map<string, char* args::*> argmap { + { "fstype", &args::fstype }, + { "fspath", &args::fspath }, + { "from", &args::from }, + }; + args a; + for (size_t i = 0; i < niov; i += 2) { + std::string s(static_cast<const char*>(iov[i].iov_base)); + if (argmap.count(s)) { + a.*(argmap[s]) = static_cast<char*>(iov[i+1].iov_base); + } + } + return sys_mount(a.from, a.fspath, a.fstype, flags, nullptr); } static void import_extra_zfs_pools(void) { - struct stat st; - int ret; + struct stat st; + int ret; - // The file '/etc/mnttab' is a LibZFS requirement and will not - // exist during cpiod phase. The functionality provided by this - // function isn't needed during that phase, so let's skip it. - if (stat("/etc/mnttab" , &st) != 0) { - return; - } + // The file '/etc/mnttab' is a LibZFS requirement and will not + // exist during cpiod phase. The functionality provided by this + // function isn't needed during that phase, so let's skip it. + if (stat("/etc/mnttab" , &st) != 0) { + return; + } - // Import extra pools mounting datasets there contained. - // Datasets from osv pool will not be mounted here. - if (access("zpool.so", X_OK) != 0) { - return; - } - vector<string> zpool_args = {"zpool", "import", "-f", "-a" }; - auto ok = osv::run("zpool.so", zpool_args, &ret); - assert(ok); + // Import extra pools mounting datasets there contained. + // Datasets from osv pool will not be mounted here. + if (access("zpool.so", X_OK) != 0) { + return; + } + vector<string> zpool_args = {"zpool", "import", "-f", "-a" }; + auto ok = osv::run("zpool.so", zpool_args, &ret); + assert(ok); - if (!ret) { - debug("zfs: extra ZFS pool(s) found.\n"); - } + if (!ret) { + debug("zfs: extra ZFS pool(s) found.\n"); + } } void pivot_rootfs(const char* path) { - int ret = sys_pivot_root(path, "/"); - if (ret) - kprintf("failed to pivot root, error = %s\n", strerror(ret)); - - auto ent = setmntent("/etc/fstab", "r"); - if (!ent) { - return; - } + int ret = sys_pivot_root(path, "/"); + if (ret) + kprintf("failed to pivot root, error = %s\n", strerror(ret)); - struct mntent *m = nullptr; - while ((m = getmntent(ent)) != nullptr) { - if (!strcmp(m->mnt_dir, "/")) { - continue; - } - - if ((m->mnt_opts != nullptr) && strcmp(m->mnt_opts, MNTOPT_DEFAULTS)) { - printf("Warning: opts %s, ignored for fs %s\n", m->mnt_opts, m->mnt_type); - } + auto ent = setmntent("/etc/fstab", "r"); + if (!ent) { + return; + } - // FIXME: Right now, ignoring mntops. In the future we may have an option parser - ret = sys_mount(m->mnt_fsname, m->mnt_dir, m->mnt_type, 0, nullptr); - if (ret) { - printf("failed to mount %s, error = %s\n", m->mnt_type, strerror(ret)); - } - } - endmntent(ent); + struct mntent *m = nullptr; + while ((m = getmntent(ent)) != nullptr) { + if (!strcmp(m->mnt_dir, "/")) { + continue; + } + + if ((m->mnt_opts != nullptr) && strcmp(m->mnt_opts, MNTOPT_DEFAULTS)) { + printf("Warning: opts %s, ignored for fs %s\n", m->mnt_opts, m->mnt_type); + } + + // FIXME: Right now, ignoring mntops. In the future we may have an option parser + ret = sys_mount(m->mnt_fsname, m->mnt_dir, m->mnt_type, 0, nullptr); + if (ret) { + printf("failed to mount %s, error = %s\n", m->mnt_type, strerror(ret)); + } + } + endmntent(ent); } extern "C" void unmount_devfs() { - int ret = sys_umount("/dev"); - if (ret) - kprintf("failed to unmount /dev, error = %s\n", strerror(ret)); + int ret = sys_umount("/dev"); + if (ret) + kprintf("failed to unmount /dev, error = %s\n", strerror(ret)); } extern "C" int mount_rofs_rootfs(bool pivot_root) { - int ret; + int ret; - if (mkdir("/rofs", 0755) < 0) - kprintf("failed to create /rofs, error = %s\n", strerror(errno)); + if (mkdir("/rofs", 0755) < 0) + kprintf("failed to create /rofs, error = %s\n", strerror(errno)); - ret = sys_mount("/dev/vblk0.1", "/rofs", "rofs", MNT_RDONLY, 0); + ret = sys_mount("/dev/vblk0.1", "/rofs", "rofs", MNT_RDONLY, 0); - if (ret) { - kprintf("failed to mount /rofs, error = %s\n", strerror(ret)); - rmdir("/rofs"); - return ret; - } + if (ret) { + kprintf("failed to mount /rofs, error = %s\n", strerror(ret)); + rmdir("/rofs"); + return ret; + } - if (pivot_root) { - pivot_rootfs("/rofs"); - } + if (pivot_root) { + pivot_rootfs("/rofs"); + } - return 0; + return 0; } extern "C" void mount_zfs_rootfs(bool pivot_root) { - if (mkdir("/zfs", 0755) < 0) - kprintf("failed to create /zfs, error = %s\n", strerror(errno)); + if (mkdir("/zfs", 0755) < 0) + kprintf("failed to create /zfs, error = %s\n", strerror(errno)); - int ret = sys_mount("/dev/vblk0.1", "/zfs", "zfs", 0, (void *)"osv/zfs"); + int ret = sys_mount("/dev/vblk0.1", "/zfs", "zfs", 0, (void *)"osv/zfs"); - if (ret) - kprintf("failed to mount /zfs, error = %s\n", strerror(ret)); + if (ret) + kprintf("failed to mount /zfs, error = %s\n", strerror(ret)); - if (!pivot_root) { - return; - } + if (!pivot_root) { + return; + } - pivot_rootfs("/zfs"); + pivot_rootfs("/zfs"); - import_extra_zfs_pools(); + import_extra_zfs_pools(); } extern "C" void unmount_rootfs(void) { - int ret; + int ret; - sys_umount("/dev"); + sys_umount("/dev"); - ret = sys_umount("/proc"); - if (ret) { - kprintf("Warning: unmount_rootfs: failed to unmount /proc, " - "error = %s\n", strerror(ret)); - } + ret = sys_umount("/proc"); + if (ret) { + kprintf("Warning: unmount_rootfs: failed to unmount /proc, " + "error = %s\n", strerror(ret)); + } - ret = sys_umount2("/", MNT_FORCE); - if (ret) { - kprintf("Warning: unmount_rootfs: failed to unmount /, " - "error = %s\n", strerror(ret)); - } + ret = sys_umount2("/", MNT_FORCE); + if (ret) { + kprintf("Warning: unmount_rootfs: failed to unmount /, " + "error = %s\n", strerror(ret)); + } } extern "C" void bio_init(void); @@ -2365,49 +2365,49 @@ extern "C" void vfs_init(void) { - const struct vfssw *fs; - - bio_init(); - lookup_init(); - vnode_init(); - task_alloc(&main_task); - - /* - * Initialize each file system. - */ - for (fs = vfssw; fs->vs_name; fs++) { - if (fs->vs_init) { - DPRINTF(VFSDB_CORE, ("VFS: initializing %s\n", - fs->vs_name)); - fs->vs_init(); - } - } - - mount_rootfs(); - unpack_bootfs(); - - // if (open("/dev/console", O_RDWR, 0) != 0) - if (console::open() != 0) - kprintf("failed to open console, error = %d\n", errno); - if (dup(0) != 1) - kprintf("failed to dup console (1)\n"); - if (dup(0) != 2) - kprintf("failed to dup console (2)\n"); - vfs_initialized = 1; + const struct vfssw *fs; + + bio_init(); + lookup_init(); + vnode_init(); + task_alloc(&main_task); + + /* + * Initialize each file system. + */ + for (fs = vfssw; fs->vs_name; fs++) { + if (fs->vs_init) { + DPRINTF(VFSDB_CORE, ("VFS: initializing %s\n", + fs->vs_name)); + fs->vs_init(); + } + } + + mount_rootfs(); + unpack_bootfs(); + + // if (open("/dev/console", O_RDWR, 0) != 0) + if (console::open() != 0) + kprintf("failed to open console, error = %d\n", errno); + if (dup(0) != 1) + kprintf("failed to dup console (1)\n"); + if (dup(0) != 2) + kprintf("failed to dup console (2)\n"); + vfs_initialized = 1; } void vfs_exit(void) { - /* Free up main_task (stores cwd data) resources */ - replace_cwd(main_task, nullptr, []() { return 0; }); - /* Unmount all file systems */ - unmount_rootfs(); - /* Finish with the bio layer */ - bio_sync(); + /* Free up main_task (stores cwd data) resources */ + replace_cwd(main_task, nullptr, []() { return 0; }); + /* Unmount all file systems */ + unmount_rootfs(); + /* Finish with the bio layer */ + bio_sync(); } void sys_panic(const char *str) { - abort("panic: %s", str); + abort("panic: %s", str); } diff --git a/lib/vfscore/mount.c b/lib/vfscore/mount.c index dac4d09c..b51b27a4 100644 --- a/lib/vfscore/mount.c +++ b/lib/vfscore/mount.c @@ -69,287 +69,287 @@ static mutex mount_lock; static const struct vfssw * fs_getfs(const char *name) { - const struct vfssw *fs; - - for (fs = vfssw; fs->vs_name; fs++) { - if (!strncmp(name, fs->vs_name, FSMAXNAMES)) - break; - } - if (!fs->vs_name) - return nullptr; - return fs; + const struct vfssw *fs; + + for (fs = vfssw; fs->vs_name; fs++) { + if (!strncmp(name, fs->vs_name, FSMAXNAMES)) + break; + } + if (!fs->vs_name) + return nullptr; + return fs; } const char* fs_getfsname(vfsops* ops) { - for (auto fs = vfssw; fs->vs_name; fs++) { - if (fs->vs_op == ops) { - return fs->vs_name; - } - } - abort(); + for (auto fs = vfssw; fs->vs_name; fs++) { + if (fs->vs_op == ops) { + return fs->vs_name; + } + } + abort(); } int sys_mount(const char *dev, const char *dir, const char *fsname, int flags, const void *data) { - const struct vfssw *fs; - struct mount *mp; - struct device *device; - struct dentry *dp_covered; - struct vnode *vp; - int error; - - kprintf("VFS: mounting %s at %s\n", fsname, dir); - - if (!dir || *dir == '\0') - return ENOENT; - - /* Find a file system. */ - if (!(fs = fs_getfs(fsname))) - return ENODEV; /* No such file system */ - - /* Open device. nullptr can be specified as a device. */ - // Allow device_open() to fail, in which case dev is interpreted - // by the file system mount routine (e.g zfs pools) - device = 0; - if (dev && strncmp(dev, "/dev/", 5) == 0) - device_open(dev + 5, DO_RDWR, &device); - - /* Check if device or directory has already been mounted. */ - // We need to avoid the situation where after we already verified that - // the mount point is free, but before we actually add it to mount_list, - // another concurrent mount adds it. So we use a new mutex to ensure - // that only one sys_mount() runs at a time. We cannot reuse the existing - // mount_lock for this purpose: If we take mount_lock and then do - // lookups, this is lock order inversion and can result in deadlock. - static mutex sys_mount_lock; - SCOPE_LOCK(sys_mount_lock); - WITH_LOCK(mount_lock) { - for (auto&& mp : mount_list) { - if (!strcmp(mp->m_path, dir) || - (device && mp->m_dev == device)) { - error = EBUSY; /* Already mounted */ - goto err1; - } - } - } - /* - * Create VFS mount entry. - */ - if (!(mp = new mount)) { - error = ENOMEM; - goto err1; - } - mp->m_count = 0; - mp->m_op = fs->vs_op; - mp->m_flags = flags; - mp->m_dev = device; - mp->m_data = nullptr; - strlcpy(mp->m_path, dir, sizeof(mp->m_path)); - strlcpy(mp->m_special, dev, sizeof(mp->m_special)); - - /* - * Get vnode to be covered in the upper file system. - */ - if (*dir == '/' && *(dir + 1) == '\0') { - /* Ignore if it mounts to global root directory. */ - dp_covered = nullptr; - } else { - if ((error = namei(dir, &dp_covered)) != 0) { - - error = ENOENT; - goto err2; - } - if (dp_covered->d_vnode->v_type != VDIR) { - error = ENOTDIR; - goto err3; - } - } - mp->m_covered = dp_covered; - - /* - * Create a root vnode for this file system. - */ - vget(mp, 0, &vp); - if (vp == nullptr) { - error = ENOMEM; - goto err3; - } - vp->v_type = VDIR; - vp->v_flags = VROOT; - vp->v_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR; - - mp->m_root = dentry_alloc(nullptr, vp, "/"); - if (!mp->m_root) { - vput(vp); - goto err3; - } - vput(vp); - - /* - * Call a file system specific routine. - */ - if ((error = VFS_MOUNT(mp, dev, flags, data)) != 0) - goto err4; - - if (mp->m_flags & MNT_RDONLY) - vp->v_mode &=~S_IWUSR; - - /* - * Insert to mount list - */ - WITH_LOCK(mount_lock) { - mount_list.push_back(mp); - } - - return 0; /* success */ + const struct vfssw *fs; + struct mount *mp; + struct device *device; + struct dentry *dp_covered; + struct vnode *vp; + int error; + + kprintf("VFS: mounting %s at %s\n", fsname, dir); + + if (!dir || *dir == '\0') + return ENOENT; + + /* Find a file system. */ + if (!(fs = fs_getfs(fsname))) + return ENODEV; /* No such file system */ + + /* Open device. nullptr can be specified as a device. */ + // Allow device_open() to fail, in which case dev is interpreted + // by the file system mount routine (e.g zfs pools) + device = 0; + if (dev && strncmp(dev, "/dev/", 5) == 0) + device_open(dev + 5, DO_RDWR, &device); + + /* Check if device or directory has already been mounted. */ + // We need to avoid the situation where after we already verified that + // the mount point is free, but before we actually add it to mount_list, + // another concurrent mount adds it. So we use a new mutex to ensure + // that only one sys_mount() runs at a time. We cannot reuse the existing + // mount_lock for this purpose: If we take mount_lock and then do + // lookups, this is lock order inversion and can result in deadlock. + static mutex sys_mount_lock; + SCOPE_LOCK(sys_mount_lock); + WITH_LOCK(mount_lock) { + for (auto&& mp : mount_list) { + if (!strcmp(mp->m_path, dir) || + (device && mp->m_dev == device)) { + error = EBUSY; /* Already mounted */ + goto err1; + } + } + } + /* + * Create VFS mount entry. + */ + if (!(mp = new mount)) { + error = ENOMEM; + goto err1; + } + mp->m_count = 0; + mp->m_op = fs->vs_op; + mp->m_flags = flags; + mp->m_dev = device; + mp->m_data = nullptr; + strlcpy(mp->m_path, dir, sizeof(mp->m_path)); + strlcpy(mp->m_special, dev, sizeof(mp->m_special)); + + /* + * Get vnode to be covered in the upper file system. + */ + if (*dir == '/' && *(dir + 1) == '\0') { + /* Ignore if it mounts to global root directory. */ + dp_covered = nullptr; + } else { + if ((error = namei(dir, &dp_covered)) != 0) { + + error = ENOENT; + goto err2; + } + if (dp_covered->d_vnode->v_type != VDIR) { + error = ENOTDIR; + goto err3; + } + } + mp->m_covered = dp_covered; + + /* + * Create a root vnode for this file system. + */ + vget(mp, 0, &vp); + if (vp == nullptr) { + error = ENOMEM; + goto err3; + } + vp->v_type = VDIR; + vp->v_flags = VROOT; + vp->v_mode = S_IFDIR | S_IRUSR | S_IWUSR | S_IXUSR; + + mp->m_root = dentry_alloc(nullptr, vp, "/"); + if (!mp->m_root) { + vput(vp); + goto err3; + } + vput(vp); + + /* + * Call a file system specific routine. + */ + if ((error = VFS_MOUNT(mp, dev, flags, data)) != 0) + goto err4; + + if (mp->m_flags & MNT_RDONLY) + vp->v_mode &=~S_IWUSR; + + /* + * Insert to mount list + */ + WITH_LOCK(mount_lock) { + mount_list.push_back(mp); + } + + return 0; /* success */ err4: - drele(mp->m_root); + drele(mp->m_root); err3: - if (dp_covered) - drele(dp_covered); + if (dp_covered) + drele(dp_covered); err2: - delete mp; + delete mp; err1: - if (device) - device_close(device); + if (device) + device_close(device); - return error; + return error; } void release_mp_dentries(struct mount *mp) { - /* Decrement referece count of root vnode */ - if (mp->m_covered) { - drele(mp->m_covered); - } + /* Decrement referece count of root vnode */ + if (mp->m_covered) { + drele(mp->m_covered); + } - /* Release root dentry */ - drele(mp->m_root); + /* Release root dentry */ + drele(mp->m_root); } int sys_umount2(const char *path, int flags) { - struct mount *mp; - int error, pathlen; + struct mount *mp; + int error, pathlen; - kprintf("VFS: unmounting %s\n", path); + kprintf("VFS: unmounting %s\n", path); - SCOPE_LOCK(mount_lock); + SCOPE_LOCK(mount_lock); - pathlen = strlen(path); - if (pathlen >= MAXPATHLEN) { - error = ENAMETOOLONG; - goto out; - } + pathlen = strlen(path); + if (pathlen >= MAXPATHLEN) { + error = ENAMETOOLONG; + goto out; + } - /* Get mount entry */ - for (auto&& tmp : mount_list) { - if (!strcmp(path, tmp->m_path)) { - mp = tmp; - goto found; - } - } + /* Get mount entry */ + for (auto&& tmp : mount_list) { + if (!strcmp(path, tmp->m_path)) { + mp = tmp; + goto found; + } + } - error = EINVAL; - goto out; + error = EINVAL; + goto out; found: - /* - * Root fs can not be unmounted. - */ - if (mp->m_covered == nullptr && !(flags & MNT_FORCE)) { - error = EINVAL; - goto out; - } - - if ((error = VFS_UNMOUNT(mp, flags)) != 0) - goto out; - mount_list.remove(mp); + /* + * Root fs can not be unmounted. + */ + if (mp->m_covered == nullptr && !(flags & MNT_FORCE)) { + error = EINVAL; + goto out; + } + + if ((error = VFS_UNMOUNT(mp, flags)) != 0) + goto out; + mount_list.remove(mp); #ifdef HAVE_BUFFERS - /* Flush all buffers */ - binval(mp->m_dev); + /* Flush all buffers */ + binval(mp->m_dev); #endif - if (mp->m_dev) - device_close(mp->m_dev); - delete mp; + if (mp->m_dev) + device_close(mp->m_dev); + delete mp; out: - return error; + return error; } int sys_umount(const char *path) { - return sys_umount2(path, 0); + return sys_umount2(path, 0); } int sys_pivot_root(const char *new_root, const char *put_old) { - struct mount *newmp = nullptr, *oldmp = nullptr; - int error; - - WITH_LOCK(mount_lock) { - for (auto&& mp : mount_list) { - if (!strcmp(mp->m_path, new_root)) { - newmp = mp; - } - if (!strcmp(mp->m_path, put_old)) { - oldmp = mp; - } - } - if (!newmp || !oldmp || newmp == oldmp) { - return EINVAL; - } - for (auto&& mp : mount_list) { - if (mp == newmp || mp == oldmp) { - continue; - } - if (!strncmp(mp->m_path, put_old, strlen(put_old))) { - return EBUSY; - } - } - if ((error = VFS_UNMOUNT(oldmp, 0)) != 0) { - return error; - } - mount_list.remove(oldmp); - - newmp->m_root->d_vnode->v_mount = newmp; - - if (newmp->m_covered) { - drele(newmp->m_covered); - } - newmp->m_covered = nullptr; - - if (newmp->m_root->d_parent) { - drele(newmp->m_root->d_parent); - } - newmp->m_root->d_parent = nullptr; - - strlcpy(newmp->m_path, "/", sizeof(newmp->m_path)); - } - return 0; + struct mount *newmp = nullptr, *oldmp = nullptr; + int error; + + WITH_LOCK(mount_lock) { + for (auto&& mp : mount_list) { + if (!strcmp(mp->m_path, new_root)) { + newmp = mp; + } + if (!strcmp(mp->m_path, put_old)) { + oldmp = mp; + } + } + if (!newmp || !oldmp || newmp == oldmp) { + return EINVAL; + } + for (auto&& mp : mount_list) { + if (mp == newmp || mp == oldmp) { + continue; + } + if (!strncmp(mp->m_path, put_old, strlen(put_old))) { + return EBUSY; + } + } + if ((error = VFS_UNMOUNT(oldmp, 0)) != 0) { + return error; + } + mount_list.remove(oldmp); + + newmp->m_root->d_vnode->v_mount = newmp; + + if (newmp->m_covered) { + drele(newmp->m_covered); + } + newmp->m_covered = nullptr; + + if (newmp->m_root->d_parent) { + drele(newmp->m_root->d_parent); + } + newmp->m_root->d_parent = nullptr; + + strlcpy(newmp->m_path, "/", sizeof(newmp->m_path)); + } + return 0; } int sys_sync(void) { - /* Call each mounted file system. */ - WITH_LOCK(mount_lock) { - for (auto&& mp : mount_list) { - VFS_SYNC(mp); - } - } + /* Call each mounted file system. */ + WITH_LOCK(mount_lock) { + for (auto&& mp : mount_list) { + VFS_SYNC(mp); + } + } #ifdef HAVE_BUFFERS - bio_sync(); + bio_sync(); #endif - return 0; + return 0; } /* @@ -360,25 +360,25 @@ sys_sync(void) static size_t count_match(const char *path, char *mount_root) { - size_t len = 0; + size_t len = 0; - while (*path && *mount_root) { - if (*path != *mount_root) - break; + while (*path && *mount_root) { + if (*path != *mount_root) + break; - path++; - mount_root++; - len++; - } - if (*mount_root != '\0') - return 0; + path++; + mount_root++; + len++; + } + if (*mount_root != '\0') + return 0; - if (len == 1 && *(path - 1) == '/') - return 1; + if (len == 1 && *(path - 1) == '/') + return 1; - if (*path == '\0' || *path == '/') - return len; - return 0; + if (*path == '\0' || *path == '/') + return len; + return 0; } /* @@ -390,28 +390,28 @@ count_match(const char *path, char *mount_root) int vfs_findroot(const char *path, struct mount **mp, char **root) { - struct mount *m = nullptr; - size_t len, max_len = 0; - - if (!path) - return -1; - - /* Find mount point from nearest path */ - SCOPE_LOCK(mount_lock); - for (auto&& tmp : mount_list) { - len = count_match(path, tmp->m_path); - if (len > max_len) { - max_len = len; - m = tmp; - } - } - if (m == nullptr) - return -1; - *root = (char *)(path + max_len); - if (**root == '/') - (*root)++; - *mp = m; - return 0; + struct mount *m = nullptr; + size_t len, max_len = 0; + + if (!path) + return -1; + + /* Find mount point from nearest path */ + SCOPE_LOCK(mount_lock); + for (auto&& tmp : mount_list) { + len = count_match(path, tmp->m_path); + if (len > max_len) { + max_len = len; + m = tmp; + } + } + if (m == nullptr) + return -1; + *root = (char *)(path + max_len); + if (**root == '/') + (*root)++; + *mp = m; + return 0; } /* @@ -420,8 +420,8 @@ vfs_findroot(const char *path, struct mount **mp, char **root) void vfs_busy(struct mount *mp) { - SCOPE_LOCK(mount_lock); - mp->m_count++; + SCOPE_LOCK(mount_lock); + mp->m_count++; } @@ -431,45 +431,45 @@ vfs_busy(struct mount *mp) void vfs_unbusy(struct mount *mp) { - SCOPE_LOCK(mount_lock); - mp->m_count--; + SCOPE_LOCK(mount_lock); + mp->m_count--; } int vfs_nullop(void) { - return 0; + return 0; } int vfs_einval(void) { - return EINVAL; + return EINVAL; } namespace osv { mount_desc to_mount_desc(mount* m) { - mount_desc ret; - ret.special = m->m_special; - ret.path = m->m_path; - ret.type = fs_getfsname(m->m_op); - // FIXME: record options - ret.options = ""; - return ret; + mount_desc ret; + ret.special = m->m_special; + ret.path = m->m_path; + ret.type = fs_getfsname(m->m_op); + // FIXME: record options + ret.options = ""; + return ret; } std::vector<mount_desc> current_mounts() { - WITH_LOCK(mount_lock) { - std::vector<mount_desc> ret; - for (auto&& mp : mount_list) { - ret.push_back(to_mount_desc(mp)); - } - return ret; - } + WITH_LOCK(mount_lock) { + std::vector<mount_desc> ret; + for (auto&& mp : mount_list) { + ret.push_back(to_mount_desc(mp)); + } + return ret; + } } } @@ -478,14 +478,14 @@ current_mounts() void mount_dump(void) { - SCOPE_LOCK(mount_lock); + SCOPE_LOCK(mount_lock); - kprintf("mount_dump\n"); - kprintf("dev count root\n"); - kprintf("-------- ----- --------\n"); + kprintf("mount_dump\n"); + kprintf("dev count root\n"); + kprintf("-------- ----- --------\n"); - for (auto&& mp : mount_list) { - kprintf("%8x %5d %s\n", mp->m_dev, mp->m_count, mp->m_path); - } + for (auto&& mp : mount_list) { + kprintf("%8x %5d %s\n", mp->m_dev, mp->m_count, mp->m_path); + } } #endif diff --git a/lib/vfscore/syscalls.c b/lib/vfscore/syscalls.c index 487d5729..b5433ece 100644 --- a/lib/vfscore/syscalls.c +++ b/lib/vfscore/syscalls.c @@ -245,72 +245,72 @@ int sys_read(struct file *fp, const struct iovec *iov, size_t niov, off_t offset, size_t *count) { - if ((fp->f_flags & FREAD) == 0) - return EBADF; - - size_t bytes = 0; - auto iovp = iov; - for (unsigned i = 0; i < niov; i++) { - if (iovp->iov_len > IOSIZE_MAX - bytes) { - return EINVAL; - } - bytes += iovp->iov_len; - iovp++; - } - - if (bytes == 0) { - *count = 0; - return 0; - } - - struct uio uio; - // Unfortunately, the current implementation of fp->read zeros the - // iov_len fields when it reads from disk, so we have to copy iov. - std::vector<iovec> copy_iov(iov, iov + niov); - uio.uio_iov = copy_iov.data(); - uio.uio_iovcnt = niov; - uio.uio_offset = offset; - uio.uio_resid = bytes; - uio.uio_rw = UIO_READ; - auto error = fp->read(&uio, (offset == -1) ? 0 : FOF_OFFSET); - *count = bytes - uio.uio_resid; - return error; + if ((fp->f_flags & FREAD) == 0) + return EBADF; + + size_t bytes = 0; + auto iovp = iov; + for (unsigned i = 0; i < niov; i++) { + if (iovp->iov_len > IOSIZE_MAX - bytes) { + return EINVAL; + } + bytes += iovp->iov_len; + iovp++; + } + + if (bytes == 0) { + *count = 0; + return 0; + } + + struct uio uio; + // Unfortunately, the current implementation of fp->read zeros the + // iov_len fields when it reads from disk, so we have to copy iov. + std::vector<iovec> copy_iov(iov, iov + niov); + uio.uio_iov = copy_iov.data(); + uio.uio_iovcnt = niov; + uio.uio_offset = offset; + uio.uio_resid = bytes; + uio.uio_rw = UIO_READ; + auto error = fp->read(&uio, (offset == -1) ? 0 : FOF_OFFSET); + *count = bytes - uio.uio_resid; + return error; } int sys_write(struct file *fp, const struct iovec *iov, size_t niov, off_t offset, size_t *count) { - if ((fp->f_flags & FWRITE) == 0) - return EBADF; - - size_t bytes = 0; - auto iovp = iov; - for (unsigned i = 0; i < niov; i++) { - if (iovp->iov_len > IOSIZE_MAX - bytes) { - return EINVAL; - } - bytes += iovp->iov_len; - iovp++; - } - - if (bytes == 0) { - *count = 0; - return 0; - } - - struct uio uio; - // Unfortunately, the current implementation of fp->write zeros the - // iov_len fields when it writes to disk, so we have to copy iov. - std::vector<iovec> copy_iov(iov, iov + niov); - uio.uio_iov = copy_iov.data(); - uio.uio_iovcnt = niov; - uio.uio_offset = offset; - uio.uio_resid = bytes; - uio.uio_rw = UIO_WRITE; - auto error = fp->write(&uio, (offset == -1) ? 0 : FOF_OFFSET); - *count = bytes - uio.uio_resid; - return error; + if ((fp->f_flags & FWRITE) == 0) + return EBADF; + + size_t bytes = 0; + auto iovp = iov; + for (unsigned i = 0; i < niov; i++) { + if (iovp->iov_len > IOSIZE_MAX - bytes) { + return EINVAL; + } + bytes += iovp->iov_len; + iovp++; + } + + if (bytes == 0) { + *count = 0; + return 0; + } + + struct uio uio; + // Unfortunately, the current implementation of fp->write zeros the + // iov_len fields when it writes to disk, so we have to copy iov. + std::vector<iovec> copy_iov(iov, iov + niov); + uio.uio_iov = copy_iov.data(); + uio.uio_iovcnt = niov; + uio.uio_offset = offset; + uio.uio_resid = bytes; + uio.uio_rw = UIO_WRITE; + auto error = fp->write(&uio, (offset == -1) ? 0 : FOF_OFFSET); + *count = bytes - uio.uio_resid; + return error; } int @@ -1221,8 +1221,8 @@ sys_readlink(char *path, char *buf, size_t bufsize, ssize_t *size) */ static bool is_timeval_valid(const struct timeval *time) { - return (time->tv_sec >= 0) && - (time->tv_usec >= 0 && time->tv_usec < 1000000); + return (time->tv_sec >= 0) && + (time->tv_usec >= 0 && time->tv_usec < 1000000); } /* @@ -1230,58 +1230,58 @@ static bool is_timeval_valid(const struct timeval *time) */ static void convert_timeval(struct timespec &to, const struct timeval *from) { - if (from) { - to.tv_sec = from->tv_sec; - to.tv_nsec = from->tv_usec * 1000; // Convert microseconds to nanoseconds - } else { - clock_gettime(CLOCK_REALTIME, &to); - } + if (from) { + to.tv_sec = from->tv_sec; + to.tv_nsec = from->tv_usec * 1000; // Convert microseconds to nanoseconds + } else { + clock_gettime(CLOCK_REALTIME, &to); + } } int sys_utimes(char *path, const struct timeval times[2], int flags) { - int error; - struct dentry *dp; - struct timespec timespec_times[2]; - - DPRINTF(VFSDB_SYSCALL, ("sys_utimes: path=%s\n", path)); - - if (times && (!is_timeval_valid(×[0]) || !is_timeval_valid(×[1]))) - return EINVAL; - - // Convert each element of timeval array to the timespec type - convert_timeval(timespec_times[0], times ? times + 0 : nullptr); - convert_timeval(timespec_times[1], times ? times + 1 : nullptr); - - if (flags & AT_SYMLINK_NOFOLLOW) { - struct dentry *ddp; - error = lookup(path, &ddp, nullptr); - if (error) { - return error; - } - - error = namei_last_nofollow(path, ddp, &dp); - if (ddp != nullptr) { - drele(ddp); - } - if (error) { - return error; - } - } else { - error = namei(path, &dp); - if (error) - return error; - } - - if (dp->d_mount->m_flags & MNT_RDONLY) { - error = EROFS; - } else { - error = vn_settimes(dp->d_vnode, timespec_times); - } - - drele(dp); - return error; + int error; + struct dentry *dp; + struct timespec timespec_times[2]; + + DPRINTF(VFSDB_SYSCALL, ("sys_utimes: path=%s\n", path)); + + if (times && (!is_timeval_valid(×[0]) || !is_timeval_valid(×[1]))) + return EINVAL; + + // Convert each element of timeval array to the timespec type + convert_timeval(timespec_times[0], times ? times + 0 : nullptr); + convert_timeval(timespec_times[1], times ? times + 1 : nullptr); + + if (flags & AT_SYMLINK_NOFOLLOW) { + struct dentry *ddp; + error = lookup(path, &ddp, nullptr); + if (error) { + return error; + } + + error = namei_last_nofollow(path, ddp, &dp); + if (ddp != nullptr) { + drele(ddp); + } + if (error) { + return error; + } + } else { + error = namei(path, &dp); + if (error) + return error; + } + + if (dp->d_mount->m_flags & MNT_RDONLY) { + error = EROFS; + } else { + error = vn_settimes(dp->d_vnode, timespec_times); + } + + drele(dp); + return error; } /* @@ -1289,7 +1289,7 @@ sys_utimes(char *path, const struct timeval times[2], int flags) */ static bool is_timespec_valid(const struct timespec &time) { - return (time.tv_sec >= 0) && + return (time.tv_sec >= 0) && ((time.tv_nsec >= 0 && time.tv_nsec <= 999999999) || time.tv_nsec == UTIME_NOW || time.tv_nsec == UTIME_OMIT); @@ -1297,48 +1297,48 @@ static bool is_timespec_valid(const struct timespec &time) void init_timespec(struct timespec &_times, const struct timespec *times) { - if (times == nullptr || times->tv_nsec == UTIME_NOW) { - clock_gettime(CLOCK_REALTIME, &_times); - } else { - _times.tv_sec = times->tv_sec; - _times.tv_nsec = times->tv_nsec; - } - return; + if (times == nullptr || times->tv_nsec == UTIME_NOW) { + clock_gettime(CLOCK_REALTIME, &_times); + } else { + _times.tv_sec = times->tv_sec; + _times.tv_nsec = times->tv_nsec; + } + return; } int sys_utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags) { - int error; - std::string ap; - struct timespec timespec_times[2]; - extern struct task *main_task; - struct dentry *dp; + int error; + std::string ap; + struct timespec timespec_times[2]; + extern struct task *main_task; + struct dentry *dp; - /* utimensat should return ENOENT when pathname is empty */ - if(pathname && pathname[0] == 0) - return ENOENT; + /* utimensat should return ENOENT when pathname is empty */ + if(pathname && pathname[0] == 0) + return ENOENT; - if (flags && !(flags & AT_SYMLINK_NOFOLLOW)) - return EINVAL; + if (flags && !(flags & AT_SYMLINK_NOFOLLOW)) + return EINVAL; - if (times && (!is_timespec_valid(times[0]) || !is_timespec_valid(times[1]))) - return EINVAL; + if (times && (!is_timespec_valid(times[0]) || !is_timespec_valid(times[1]))) + return EINVAL; - init_timespec(timespec_times[0], times ? times + 0 : nullptr); - init_timespec(timespec_times[1], times ? times + 1 : nullptr); + init_timespec(timespec_times[0], times ? times + 0 : nullptr); + init_timespec(timespec_times[1], times ? times + 1 : nullptr); - if (pathname && pathname[0] == '/') { + if (pathname && pathname[0] == '/') { ap = pathname; - } else if (dirfd == AT_FDCWD) { + } else if (dirfd == AT_FDCWD) { if (!pathname) return EFAULT; ap = std::string(main_task->t_cwd) + "/" + pathname; - } else { - struct file *fp; - fileref f(fileref_from_fd(dirfd)); + } else { + struct file *fp; + fileref f(fileref_from_fd(dirfd)); - if (!f) + if (!f) return EBADF; fp = f.get(); @@ -1355,132 +1355,132 @@ sys_utimensat(int dirfd, const char *pathname, const struct timespec times[2], i ap = fp->f_dentry->d_path; ap = std::string(fp->f_dentry->d_mount->m_path) + "/" + ap; - } + } - /* FIXME: Add support for AT_SYMLINK_NOFOLLOW */ + /* FIXME: Add support for AT_SYMLINK_NOFOLLOW */ - error = namei(ap.c_str(), &dp); + error = namei(ap.c_str(), &dp); - if (error) - return error; + if (error) + return error; - if (dp->d_mount->m_flags & MNT_RDONLY) { - error = EROFS; - } else { - if (vn_access(dp->d_vnode, VWRITE)) { - return EACCES; - } + if (dp->d_mount->m_flags & MNT_RDONLY) { + error = EROFS; + } else { + if (vn_access(dp->d_vnode, VWRITE)) { + return EACCES; + } if (times && - (times[0].tv_nsec != UTIME_NOW || times[1].tv_nsec != UTIME_NOW) && - (times[0].tv_nsec != UTIME_OMIT || times[1].tv_nsec != UTIME_OMIT) && + (times[0].tv_nsec != UTIME_NOW || times[1].tv_nsec != UTIME_NOW) && + (times[0].tv_nsec != UTIME_OMIT || times[1].tv_nsec != UTIME_OMIT) && (!(dp->d_vnode->v_mode & ~VAPPEND))) return EPERM; - error = vn_settimes(dp->d_vnode, timespec_times); - } + error = vn_settimes(dp->d_vnode, timespec_times); + } - drele(dp); - return error; + drele(dp); + return error; } int sys_futimens(int fd, const struct timespec times[2]) { - struct file *fp; + struct file *fp; - fileref f(fileref_from_fd(fd)); - if (!f) - return EBADF; + fileref f(fileref_from_fd(fd)); + if (!f) + return EBADF; - fp = f.get(); + fp = f.get(); - if (!fp->f_dentry) - return EBADF; + if (!fp->f_dentry) + return EBADF; - std::string pathname = fp->f_dentry->d_path; - auto error = sys_utimensat(AT_FDCWD, pathname.c_str(), times, 0); - return error; + std::string pathname = fp->f_dentry->d_path; + auto error = sys_utimensat(AT_FDCWD, pathname.c_str(), times, 0); + return error; } int sys_fallocate(struct file *fp, int mode, loff_t offset, loff_t len) { - int error; - struct vnode *vp; - - DPRINTF(VFSDB_SYSCALL, ("sys_fallocate: fp=%x", fp)); - - if (!fp->f_dentry || !(fp->f_flags & FWRITE)) { - return EBADF; - } - - if (offset < 0 || len <= 0) { - return EINVAL; - } - - // Strange, but that's what Linux returns. - if ((mode & FALLOC_FL_PUNCH_HOLE) && !(mode & FALLOC_FL_KEEP_SIZE)) { - return ENOTSUP; - } - - vp = fp->f_dentry->d_vnode; - vn_lock(vp); - - // NOTE: It's not detected here whether or not the device underlying - // the fs is a block device. It's up to the fs itself tell us whether - // or not fallocate is supported. See below: - if (vp->v_type != VREG && vp->v_type != VDIR) { - error = ENODEV; - goto ret; - } - - // EOPNOTSUPP here means that the underlying file system - // referred by vp doesn't support fallocate. - if (!vp->v_op->vop_fallocate) { - error = EOPNOTSUPP; - goto ret; - } - - error = VOP_FALLOCATE(vp, mode, offset, len); + int error; + struct vnode *vp; + + DPRINTF(VFSDB_SYSCALL, ("sys_fallocate: fp=%x", fp)); + + if (!fp->f_dentry || !(fp->f_flags & FWRITE)) { + return EBADF; + } + + if (offset < 0 || len <= 0) { + return EINVAL; + } + + // Strange, but that's what Linux returns. + if ((mode & FALLOC_FL_PUNCH_HOLE) && !(mode & FALLOC_FL_KEEP_SIZE)) { + return ENOTSUP; + } + + vp = fp->f_dentry->d_vnode; + vn_lock(vp); + + // NOTE: It's not detected here whether or not the device underlying + // the fs is a block device. It's up to the fs itself tell us whether + // or not fallocate is supported. See below: + if (vp->v_type != VREG && vp->v_type != VDIR) { + error = ENODEV; + goto ret; + } + + // EOPNOTSUPP here means that the underlying file system + // referred by vp doesn't support fallocate. + if (!vp->v_op->vop_fallocate) { + error = EOPNOTSUPP; + goto ret; + } + + error = VOP_FALLOCATE(vp, mode, offset, len); ret: - vn_unlock(vp); - return error; + vn_unlock(vp); + return error; } int sys_chmod(const char *path, mode_t mode) { - int error; - struct dentry *dp; - DPRINTF(VFSDB_SYSCALL, ("sys_chmod: path=%s\n", path)); - error = namei(path, &dp); - if (error) - return error; - if (dp->d_mount->m_flags & MNT_RDONLY) { - error = EROFS; - } else { - error = vn_setmode(dp->d_vnode, mode); - } - drele(dp); - return error; + int error; + struct dentry *dp; + DPRINTF(VFSDB_SYSCALL, ("sys_chmod: path=%s\n", path)); + error = namei(path, &dp); + if (error) + return error; + if (dp->d_mount->m_flags & MNT_RDONLY) { + error = EROFS; + } else { + error = vn_setmode(dp->d_vnode, mode); + } + drele(dp); + return error; } int sys_fchmod(int fd, mode_t mode) { - fileref f(fileref_from_fd(fd)); - if (!f) - return EBADF; - // Posix is ambivalent on what fchmod() should do on an fd that does not - // refer to a real file. It suggests an implementation may (but not must) - // fail EINVAL on a pipe, can behave in an "unspecified" manner on a - // socket, and for a STREAM, it must succeed and do nothing. Linux seems - // to just do the last thing (do nothing and succeed). - if (!f->f_dentry) { - return 0; - } - if (f->f_dentry->d_mount->m_flags & MNT_RDONLY) { - return EROFS; - } else { - return vn_setmode(f->f_dentry->d_vnode, mode); - } + fileref f(fileref_from_fd(fd)); + if (!f) + return EBADF; + // Posix is ambivalent on what fchmod() should do on an fd that does not + // refer to a real file. It suggests an implementation may (but not must) + // fail EINVAL on a pipe, can behave in an "unspecified" manner on a + // socket, and for a STREAM, it must succeed and do nothing. Linux seems + // to just do the last thing (do nothing and succeed). + if (!f->f_dentry) { + return 0; + } + if (f->f_dentry->d_mount->m_flags & MNT_RDONLY) { + return EROFS; + } else { + return vn_setmode(f->f_dentry->d_vnode, mode); + } } diff --git a/lib/vfscore/task.c b/lib/vfscore/task.c index 7a355034..b2a028c6 100644 --- a/lib/vfscore/task.c +++ b/lib/vfscore/task.c @@ -48,7 +48,7 @@ task_alloc(struct task **pt) { struct task *t; - // FIXME: where do we free task ? + // FIXME: where do we free task ? if (!(t = new task)) return ENOMEM; memset(t, 0, sizeof(struct task)); @@ -160,8 +160,8 @@ task_conv(struct task *t, const char *cpath, int acc, char *full) */ int vfs_dname_copy(char *dest, const char *src, size_t size) { - if (strlcpy(dest, src, size) >= size) { - return -1; - } - return 0; + if (strlcpy(dest, src, size) >= size) { + return -1; + } + return 0; } diff --git a/lib/vfscore/vfs.h b/lib/vfscore/vfs.h index d86ef957..2b825521 100644 --- a/lib/vfscore/vfs.h +++ b/lib/vfscore/vfs.h @@ -120,7 +120,7 @@ int sys_truncate(char *path, off_t length); int sys_readlink(char *path, char *buf, size_t bufsize, ssize_t *size); int sys_utimes(char *path, const struct timeval times[2], int flags); int sys_utimensat(int dirfd, const char *pathname, - const struct timespec times[2], int flags); + const struct timespec times[2], int flags); int sys_futimens(int fd, const struct timespec times[2]); int sys_fallocate(struct file *fp, int mode, loff_t offset, loff_t len); diff --git a/lib/vfscore/vnode.c b/lib/vfscore/vnode.c index a292344f..119ed870 100644 --- a/lib/vfscore/vnode.c +++ b/lib/vfscore/vnode.c @@ -371,22 +371,22 @@ vn_stat(struct vnode *vp, struct stat *st) int vn_settimes(struct vnode *vp, struct timespec times[2]) { - struct vattr vattr; - struct vattr *vap; - int error; - - vap = &vattr; - memset(vap, 0, sizeof(struct vattr)); - - vap->va_atime = times[0]; - vap->va_mtime = times[1]; - vap->va_mask = ((times[0].tv_nsec == UTIME_OMIT) ? 0 : AT_ATIME) - | ((times[1].tv_nsec == UTIME_OMIT) ? 0 : AT_MTIME); - vn_lock(vp); - error = VOP_SETATTR(vp, vap); - vn_unlock(vp); - - return error; + struct vattr vattr; + struct vattr *vap; + int error; + + vap = &vattr; + memset(vap, 0, sizeof(struct vattr)); + + vap->va_atime = times[0]; + vap->va_mtime = times[1]; + vap->va_mask = ((times[0].tv_nsec == UTIME_OMIT) ? 0 : AT_ATIME) + | ((times[1].tv_nsec == UTIME_OMIT) ? 0 : AT_MTIME); + vn_lock(vp); + error = VOP_SETATTR(vp, vap); + vn_unlock(vp); + + return error; } /* @@ -395,15 +395,15 @@ vn_settimes(struct vnode *vp, struct timespec times[2]) int vn_setmode(struct vnode *vp, mode_t new_mode) { - struct vattr vattr; - memset(&vattr, 0, sizeof(vattr)); - vattr.va_mode = new_mode; - vattr.va_mask = AT_MODE; - vn_lock(vp); - vp->v_mode = new_mode; - int error = VOP_SETATTR(vp, &vattr); - vn_unlock(vp); - return error; + struct vattr vattr; + memset(&vattr, 0, sizeof(vattr)); + vattr.va_mode = new_mode; + vattr.va_mask = AT_MODE; + vn_lock(vp); + vp->v_mode = new_mode; + int error = VOP_SETATTR(vp, &vattr); + vn_unlock(vp); + return error; } /* -- 2.19.2 _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/minios-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |