Changeset View
Changeset View
Standalone View
Standalone View
sys/fs/tarfs/tarfs_vfsops.c
Show First 20 Lines • Show All 283 Lines • ▼ Show 20 Lines | |||||
* - Returns 0 if the node was found, ENOENT if it was not, and some other | * - Returns 0 if the node was found, ENOENT if it was not, and some other | ||||
* positive errno value on failure. | * positive errno value on failure. | ||||
*/ | */ | ||||
static int | static int | ||||
tarfs_lookup_path(struct tarfs_mount *tmp, char *name, size_t namelen, | tarfs_lookup_path(struct tarfs_mount *tmp, char *name, size_t namelen, | ||||
char **endp, char **sepp, struct tarfs_node **retparent, | char **endp, char **sepp, struct tarfs_node **retparent, | ||||
struct tarfs_node **retnode, boolean_t create_dirs) | struct tarfs_node **retnode, boolean_t create_dirs) | ||||
{ | { | ||||
struct componentname cn; | struct componentname cn = { }; | ||||
struct tarfs_node *parent, *tnp; | struct tarfs_node *parent, *tnp; | ||||
char *sep; | char *sep; | ||||
size_t len; | size_t len; | ||||
int error; | int error; | ||||
boolean_t do_lookup; | boolean_t do_lookup; | ||||
MPASS(name != NULL && namelen != 0); | MPASS(name != NULL && namelen != 0); | ||||
do_lookup = true; | do_lookup = true; | ||||
error = 0; | error = 0; | ||||
parent = tnp = tmp->root; | parent = tnp = tmp->root; | ||||
if (tnp == NULL) | if (tnp == NULL) | ||||
panic("%s: root node not yet created", __func__); | panic("%s: root node not yet created", __func__); | ||||
bzero(&cn, sizeof(cn)); | |||||
TARFS_DPF(LOOKUP, "%s: Full path: %.*s\n", __func__, (int)namelen, | TARFS_DPF(LOOKUP, "%s: Full path: %.*s\n", __func__, (int)namelen, | ||||
name); | name); | ||||
sep = NULL; | sep = NULL; | ||||
for (;;) { | for (;;) { | ||||
/* skip leading slash(es) */ | /* skip leading slash(es) */ | ||||
while (name[0] == '/' && namelen > 0) | while (name[0] == '/' && namelen > 0) | ||||
name++, namelen--; | name++, namelen--; | ||||
/* did we reach the end? */ | /* did we reach the end? */ | ||||
if (namelen == 0 || name[0] == '\0') { | if (namelen == 0 || name[0] == '\0') { | ||||
name = do_lookup ? NULL : cn.cn_nameptr; | name = do_lookup ? NULL : cn.cn_nameptr; | ||||
namelen = do_lookup ? 0 : cn.cn_namelen; | namelen = do_lookup ? 0 : cn.cn_namelen; | ||||
break; | break; | ||||
} | } | ||||
/* locate the next separator */ | /* locate the next separator */ | ||||
for (sep = name, len = 0; | for (sep = name, len = 0; | ||||
*sep != '\0' && *sep != '/' && len < namelen; | *sep != '\0' && *sep != '/' && len < namelen; | ||||
sep++, len++) | sep++, len++) | ||||
/* nothing */ ; | /* nothing */ ; | ||||
/* check for . and .. */ | /* check for . and .. */ | ||||
if (name[0] == '.' && len <= 2) { | if (name[0] == '.' && len == 1) { | ||||
if (len == 1) { | |||||
/* . */ | |||||
name += len; | name += len; | ||||
namelen -= len; | namelen -= len; | ||||
continue; | continue; | ||||
} else if (name[1] == '.') { | } | ||||
/* .. */ | if (name[0] == '.' && name[1] == '.' && len == 2) { | ||||
allanjude: this could stuff be an `else if` to avoid the extra test if we already matched len == 1? | |||||
Done Inline ActionsThat's how it used to be, but it wasn't very readable. I trust the compiler to figure it out. des: That's how it used to be, but it wasn't very readable. I trust the compiler to figure it out. | |||||
if (tnp == tmp->root) { | if (tnp == tmp->root) { | ||||
error = EINVAL; | error = EINVAL; | ||||
break; | break; | ||||
} | } | ||||
tnp = tnp->parent; | tnp = parent; | ||||
parent = tnp->parent; | parent = tnp->parent; | ||||
name += len; | name += len; | ||||
namelen -= len; | namelen -= len; | ||||
continue; | continue; | ||||
} | } | ||||
} | |||||
/* create parent if necessary */ | /* create parent if necessary */ | ||||
if (!do_lookup) { | if (!do_lookup) { | ||||
TARFS_DPF(ALLOC, "%s: creating %.*s\n", __func__, | TARFS_DPF(ALLOC, "%s: creating %.*s\n", __func__, | ||||
(int)cn.cn_namelen, cn.cn_nameptr); | (int)cn.cn_namelen, cn.cn_nameptr); | ||||
error = tarfs_alloc_node(tmp, cn.cn_nameptr, | error = tarfs_alloc_node(tmp, cn.cn_nameptr, | ||||
cn.cn_namelen, VDIR, -1, 0, tmp->mtime, 0, 0, | cn.cn_namelen, VDIR, -1, 0, tmp->mtime, 0, 0, | ||||
DEFDIRMODE, 0, NULL, NODEV, parent, &tnp); | DEFDIRMODE, 0, NULL, NODEV, parent, &tnp); | ||||
▲ Show 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | |||||
static int | static int | ||||
tarfs_alloc_one(struct tarfs_mount *tmp, off_t *blknump) | tarfs_alloc_one(struct tarfs_mount *tmp, off_t *blknump) | ||||
{ | { | ||||
char block[TARFS_BLOCKSIZE]; | char block[TARFS_BLOCKSIZE]; | ||||
struct ustar_header *hdrp = (struct ustar_header *)block; | struct ustar_header *hdrp = (struct ustar_header *)block; | ||||
struct sbuf *namebuf = NULL; | struct sbuf *namebuf = NULL; | ||||
char *exthdr = NULL, *name = NULL, *link = NULL; | char *exthdr = NULL, *name = NULL, *link = NULL; | ||||
off_t blknum = *blknump; | off_t blknum = *blknump; | ||||
int64_t num; | |||||
int endmarker = 0; | int endmarker = 0; | ||||
char *namep, *sep; | char *namep, *sep; | ||||
struct tarfs_node *parent, *tnp; | struct tarfs_node *parent, *tnp; | ||||
size_t namelen = 0, linklen = 0, realsize = 0, sz; | size_t namelen = 0, linklen = 0, realsize = 0, sz; | ||||
ssize_t res; | ssize_t res; | ||||
dev_t rdev; | dev_t rdev; | ||||
gid_t gid; | gid_t gid; | ||||
mode_t mode; | mode_t mode; | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | again: | ||||
if (!tarfs_checksum(hdrp)) { | if (!tarfs_checksum(hdrp)) { | ||||
TARFS_DPF(ALLOC, "%s: header checksum failed at %zu\n", | TARFS_DPF(ALLOC, "%s: header checksum failed at %zu\n", | ||||
__func__, TARFS_BLOCKSIZE * (blknum - 1)); | __func__, TARFS_BLOCKSIZE * (blknum - 1)); | ||||
error = EINVAL; | error = EINVAL; | ||||
goto bad; | goto bad; | ||||
} | } | ||||
/* get standard attributes */ | /* get standard attributes */ | ||||
mode = tarfs_str2int64(hdrp->mode, sizeof(hdrp->mode)); | num = tarfs_str2int64(hdrp->mode, sizeof(hdrp->mode)); | ||||
uid = tarfs_str2int64(hdrp->uid, sizeof(hdrp->uid)); | if (num < 0 || num > ALLPERMS) { | ||||
gid = tarfs_str2int64(hdrp->gid, sizeof(hdrp->gid)); | TARFS_DPF(ALLOC, "%s: invalid file mode at %zu\n", | ||||
sz = tarfs_str2int64(hdrp->size, sizeof(hdrp->size)); | __func__, TARFS_BLOCKSIZE * (blknum - 1)); | ||||
mode = S_IRUSR; | |||||
} else { | |||||
mode = num; | |||||
} | |||||
num = tarfs_str2int64(hdrp->uid, sizeof(hdrp->uid)); | |||||
if (num < 0 || num > UID_MAX) { | |||||
TARFS_DPF(ALLOC, "%s: UID out of range at %zu\n", | |||||
__func__, TARFS_BLOCKSIZE * (blknum - 1)); | |||||
uid = tmp->root->uid; | |||||
mode &= ~S_ISUID; | |||||
} else { | |||||
uid = num; | |||||
} | |||||
num = tarfs_str2int64(hdrp->gid, sizeof(hdrp->gid)); | |||||
if (num < 0 || num > GID_MAX) { | |||||
TARFS_DPF(ALLOC, "%s: GID out of range at %zu\n", | |||||
__func__, TARFS_BLOCKSIZE * (blknum - 1)); | |||||
gid = tmp->root->gid; | |||||
mode &= ~S_ISGID; | |||||
} else { | |||||
gid = num; | |||||
} | |||||
num = tarfs_str2int64(hdrp->size, sizeof(hdrp->size)); | |||||
if (num < 0) { | |||||
TARFS_DPF(ALLOC, "%s: negative size at %zu\n", | |||||
__func__, TARFS_BLOCKSIZE * (blknum - 1)); | |||||
error = EINVAL; | |||||
goto bad; | |||||
} else { | |||||
sz = num; | |||||
} | |||||
mtime = tarfs_str2int64(hdrp->mtime, sizeof(hdrp->mtime)); | mtime = tarfs_str2int64(hdrp->mtime, sizeof(hdrp->mtime)); | ||||
rdev = NODEV; | rdev = NODEV; | ||||
TARFS_DPF(ALLOC, "%s: [%c] %zu @%jd %o %d:%d\n", __func__, | TARFS_DPF(ALLOC, "%s: [%c] %zu @%jd %o %d:%d\n", __func__, | ||||
hdrp->typeflag[0], sz, (intmax_t)mtime, mode, uid, gid); | hdrp->typeflag[0], sz, (intmax_t)mtime, mode, uid, gid); | ||||
/* extended header? */ | /* extended header? */ | ||||
if (hdrp->typeflag[0] == TAR_TYPE_GLOBAL_EXTHDR) { | if (hdrp->typeflag[0] == TAR_TYPE_GLOBAL_EXTHDR) { | ||||
printf("%s: unsupported global extended header at %zu\n", | printf("%s: unsupported global extended header at %zu\n", | ||||
▲ Show 20 Lines • Show All 246 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static int | static int | ||||
tarfs_alloc_mount(struct mount *mp, struct vnode *vp, | tarfs_alloc_mount(struct mount *mp, struct vnode *vp, | ||||
uid_t root_uid, gid_t root_gid, mode_t root_mode, | uid_t root_uid, gid_t root_gid, mode_t root_mode, | ||||
struct tarfs_mount **tmpp) | struct tarfs_mount **tmpp) | ||||
{ | { | ||||
struct vattr va; | struct vattr va; | ||||
struct thread *td = curthread; | struct thread *td = curthread; | ||||
char *fullpath; | |||||
struct tarfs_mount *tmp; | struct tarfs_mount *tmp; | ||||
struct tarfs_node *root; | struct tarfs_node *root; | ||||
off_t blknum; | off_t blknum; | ||||
time_t mtime; | time_t mtime; | ||||
int error; | int error; | ||||
KASSERT(tmpp != NULL, ("tarfs mount return is NULL")); | KASSERT(tmpp != NULL, ("tarfs mount return is NULL")); | ||||
ASSERT_VOP_LOCKED(vp, __func__); | ASSERT_VOP_LOCKED(vp, __func__); | ||||
tmp = NULL; | tmp = NULL; | ||||
fullpath = NULL; | |||||
TARFS_DPF(ALLOC, "%s: Allocating tarfs mount structure for vp %p\n", | TARFS_DPF(ALLOC, "%s: Allocating tarfs mount structure for vp %p\n", | ||||
__func__, vp); | __func__, vp); | ||||
/* Get source metadata */ | /* Get source metadata */ | ||||
error = VOP_GETATTR(vp, &va, td->td_ucred); | error = VOP_GETATTR(vp, &va, td->td_ucred); | ||||
if (error != 0) { | if (error != 0) { | ||||
return (error); | return (error); | ||||
} | } | ||||
VOP_UNLOCK(vp); | VOP_UNLOCK(vp); | ||||
mtime = va.va_mtime.tv_sec; | mtime = va.va_mtime.tv_sec; | ||||
/* Allocate and initialize tarfs mount structure */ | /* Allocate and initialize tarfs mount structure */ | ||||
tmp = (struct tarfs_mount *)malloc(sizeof(struct tarfs_mount), | tmp = malloc(sizeof(*tmp), M_TARFSMNT, M_WAITOK | M_ZERO); | ||||
M_TARFSMNT, M_WAITOK | M_ZERO); | |||||
TARFS_DPF(ALLOC, "%s: Allocated mount structure\n", __func__); | TARFS_DPF(ALLOC, "%s: Allocated mount structure\n", __func__); | ||||
mp->mnt_data = tmp; | mp->mnt_data = tmp; | ||||
mtx_init(&tmp->allnode_lock, "tarfs allnode lock", NULL, | mtx_init(&tmp->allnode_lock, "tarfs allnode lock", NULL, | ||||
MTX_DEF); | MTX_DEF); | ||||
TAILQ_INIT(&tmp->allnodes); | TAILQ_INIT(&tmp->allnodes); | ||||
tmp->ino_unr = new_unrhdr(TARFS_MININO, INT_MAX, &tmp->allnode_lock); | tmp->ino_unr = new_unrhdr(TARFS_MININO, INT_MAX, &tmp->allnode_lock); | ||||
tmp->vp = vp; | tmp->vp = vp; | ||||
Show All 28 Lines | tarfs_alloc_mount(struct mount *mp, struct vnode *vp, | ||||
} while (blknum != TAR_EOF); | } while (blknum != TAR_EOF); | ||||
*tmpp = tmp; | *tmpp = tmp; | ||||
TARFS_DPF(ALLOC, "%s: pfsmnt_root %p\n", __func__, tmp->root); | TARFS_DPF(ALLOC, "%s: pfsmnt_root %p\n", __func__, tmp->root); | ||||
return (0); | return (0); | ||||
bad: | bad: | ||||
if (tmp != NULL) | |||||
tarfs_free_mount(tmp); | tarfs_free_mount(tmp); | ||||
free(fullpath, M_TEMP); | |||||
return (error); | return (error); | ||||
} | } | ||||
/* | /* | ||||
* VFS Operations. | * VFS Operations. | ||||
*/ | */ | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 237 Lines • ▼ Show 20 Lines | tarfs_vget(struct mount *mp, ino_t ino, int lkflags, struct vnode **vpp) | ||||
TAILQ_FOREACH(tnp, &tmp->allnodes, entries) { | TAILQ_FOREACH(tnp, &tmp->allnodes, entries) { | ||||
if (tnp->ino == ino) | if (tnp->ino == ino) | ||||
break; | break; | ||||
} | } | ||||
TARFS_DPF(FS, "%s: search of all nodes found %p\n", __func__, tnp); | TARFS_DPF(FS, "%s: search of all nodes found %p\n", __func__, tnp); | ||||
if (tnp == NULL) | if (tnp == NULL) | ||||
return (ENOENT); | return (ENOENT); | ||||
error = getnewvnode("tarfs", mp, &tarfs_vnodeops, &vp); | (void)getnewvnode("tarfs", mp, &tarfs_vnodeops, &vp); | ||||
Done Inline Actionsand here especially. imp: and here especially. | |||||
if (error != 0) | |||||
goto bad; | |||||
TARFS_DPF(FS, "%s: allocated vnode\n", __func__); | TARFS_DPF(FS, "%s: allocated vnode\n", __func__); | ||||
vp->v_data = tnp; | vp->v_data = tnp; | ||||
vp->v_type = tnp->type; | vp->v_type = tnp->type; | ||||
tnp->vnode = vp; | tnp->vnode = vp; | ||||
lockmgr(vp->v_vnlock, lkflags, NULL); | lockmgr(vp->v_vnlock, lkflags, NULL); | ||||
error = insmntque(vp, mp); | error = insmntque(vp, mp); | ||||
if (error != 0) | if (error != 0) | ||||
▲ Show 20 Lines • Show All 56 Lines • Show Last 20 Lines |
this could stuff be an else if to avoid the extra test if we already matched len == 1?