📄 rootfs.c
字号:
} l = strlen(node->symlink); if (l > *bufsize) memcpy(buf, node->symlink, *bufsize); else memcpy(buf, node->symlink, l); *bufsize = l; return 0;error1: return err;}static introotfs_opendir(void *_ns, void *_node, void **cookie){ nspace *ns; vnode *node; int err; dirpos *pos; ns = (nspace *) _ns; node = (vnode *) _node; if (!MY_S_ISDIR(node->mode)) { err = ENOTDIR; goto error1; } pos = (dirpos *) malloc(sizeof(dirpos)); if (!pos) { err = ENOMEM; goto error1; } if (new_lock(&pos->lock, "rootdirlock") < 0) { err = EINVAL; goto error2; } pos->pos = 0; pos->name[0] = '\0'; *cookie = pos; return 0;error2: free(pos);error1: return err;}static introotfs_closedir(void *_ns, void *_node, void *_cookie){ return 0;}static introotfs_free_dircookie(void *_ns, void *_node, void *_cookie){ nspace *ns; vnode *node; dirpos *cookie; ns = (nspace *) _ns; node = (vnode *) _node; cookie = (dirpos *) _cookie; free_lock(&cookie->lock); free(cookie); return 0;}static introotfs_rewinddir(void *_ns, void *_node, void *_cookie){ nspace *ns; vnode *node; dirpos *cookie; ns = (nspace *) _ns; node = (vnode *) _node; cookie = (dirpos *) _cookie; LOCK(cookie->lock); cookie->pos = 0; cookie->name[0] = '\0'; UNLOCK(cookie->lock); return 0;}static introotfs_readdir(void *_ns, void *_node, void *_cookie, long *num, struct my_dirent *buf, size_t bufsize){ nspace *ns; vnode *node; dirpos *cookie; char *e, *q; struct my_dirent *p; long i; vnode *vn; vnode_id vnid; char *name, *last; int sl, rl; ns = (nspace *) _ns; node = (vnode *) _node; cookie = (dirpos *) _cookie; LOCK(ns->lock); LOCK(cookie->lock); vn = node->head; p = (struct my_dirent *) buf; e = (char *) buf + bufsize; if (cookie->pos > 2) while (vn && (strcmp(cookie->name, vn->name) >= 0)) vn = vn->next; for(i=0; (i < *num) && ((cookie->pos < 2) || vn); i++, cookie->pos++) { switch(cookie->pos) { case 0: name = "."; vnid = node->vnid; break; case 1: name = ".."; vnid = node->parent->vnid; break; default: name = vn->name; vnid = vn->vnid; vn = vn->next; break; } sl = strlen(name) + 1; rl = sizeof(struct my_dirent) + sl - 1; if ((char *)p + rl > e) break; last = name; p->d_reclen = (rl + 7) & ~7; p->d_ino = vnid; memcpy(p->d_name, name, sl); p = (struct my_dirent *)((char *)p + p->d_reclen); } if ((cookie->pos > 2) && (i > 0)) strcpy(cookie->name, last); *num = i;exit: UNLOCK(cookie->lock); UNLOCK(ns->lock); return 0;}static introotfs_rstat(void *_ns, void *_node, struct my_stat *st){ nspace *ns; vnode *node; ns = (nspace *) _ns; node = (vnode *) _node; LOCK(ns->lock); st->dev = ns->nsid; st->ino = node->vnid; st->mode = node->mode; st->nlink = 1; st->uid = node->uid; st->gid = node->gid; st->size = 0; st->blksize = 0; st->atime = st->ctime = st->mtime = node->mtime; UNLOCK(ns->lock); return 0;}static introotfs_wstat(void *_ns, void *_node, struct my_stat *st, long mask){ nspace *ns; vnode *node; ns = (nspace *) _ns; node = (vnode *) _node; if (mask & WSTAT_SIZE) return EINVAL; LOCK(ns->lock); if (mask & WSTAT_MODE) node->mode = (node->mode & MY_S_IFMT) | (st->mode & ~MY_S_IFMT); if (mask & WSTAT_UID) node->uid = st->uid; if (mask & WSTAT_GID) node->gid = st->gid; if (mask & WSTAT_MTIME) node->mtime = st->mtime; if (mask & WSTAT_ATIME) node->mtime = st->atime; UNLOCK(ns->lock); return 0;}static introotfs_mount(nspace_id nsid, const char *device, ulong flags, void *parms, size_t len, void **data, vnode_id *vnid){ int err; nspace *ns; vnode *root; vnode_id rvnid; if (device || parms || (len != 0)) { err = EINVAL; goto error1; } ns = (nspace *) malloc(sizeof(nspace)); if (!ns) { err = ENOMEM; goto error1; } root = (vnode *) malloc(sizeof(vnode)); if (!root) { err = ENOMEM; goto error2; } rvnid = 1; ns->nsid = nsid; ns->vnnum = 0; ns->nxvnid = rvnid; ns->root = root; if (new_lock(&ns->lock, "rootfs") < 0) { err = -1; goto error3; } ns->skiplist = NewSL(&compare_vnode, NULL, NO_DUPLICATES); if (!ns->skiplist) { err = -1; goto error4; } root->vnid = rvnid; root->parent = root; root->ns = ns; root->removed = FALSE; root->name = NULL; root->next = root->prev = NULL; root->head = NULL; root->symlink = NULL; /* ### do it for real */ root->uid = 0; root->gid = 0; root->mode = MY_S_IFDIR | 0777; root->mtime = time(NULL); err = new_vnode(nsid, rvnid, root); if (err) goto error5; *data = ns; *vnid = rvnid; return 0;error5: FreeSL(ns->skiplist);error4: free_lock(&ns->lock);error3: free(root);error2: free(ns);error1: return err;}static introotfs_unmount(void *_ns){ nspace *ns; vnode *vn, *avn; ns = (nspace *) _ns; vn = ns->root; while (TRUE) { while(vn->head) vn = vn->head; vn = vn->parent; if (vn == ns->root) break; avn = vn->head; if (avn->prev) avn->prev->next = avn->next; else vn->head = avn->next; if (avn->next) avn->next->prev = avn->prev; rootfs_remove_vnode(ns, avn, TRUE); } free(ns->root); free_lock(&ns->lock); FreeSL(ns->skiplist); free(ns); return 0;}/* ### should do real permission check */static introotfs_access(void *_ns, void *_node, int mode){ return 0;}static intcompare_vnode(vnode *vna, vnode *vnb){ if (vna->vnid > vnb->vnid) return 1; else if (vna->vnid < vnb->vnid) return -1; else return 0;}static intdo_create(nspace *ns, vnode *dir, const char *name, mode_t mode, vnode **vnp){ int err; int c; vnode *vn, *pvn, *nvn; char *buf; vnode_id vnid; if (!MY_S_ISDIR(dir->mode)) { err = ENOTDIR; goto error1; } /* make sure we are not trying to create something in a directory that has been removed. */ if (dir->removed) { err = ENOENT; goto error1; } /* filter the name: can't be '.', or '..' */ if (!strcmp(name, ".") || !strcmp(name, "..")) { err = EEXIST; goto error1; } /* lookup the name in the directory */ vn = dir->head; while (vn) { c = strcmp(name, vn->name); if (c < 0) vn = NULL; if (c <= 0) break; vn = vn->next; } /* if it was found, report an error. */ if (vn) { err = EEXIST; goto error1; } /* allocate a vnode and fill it */ vn = NULL; buf = NULL; vn = (vnode *) malloc(sizeof(vnode)); buf = (char *) malloc(strlen(name)+1); if (!vn || !buf) { err = ENOMEM; goto error2; } strcpy(buf, name); vnid = ++ns->nxvnid; vn->vnid = vnid; vn->parent = dir; vn->ns = ns; vn->removed = FALSE; vn->name = buf; vn->mode = mode; vn->uid = 0; vn->gid = 0; dir->mtime = vn->mtime = time(NULL); pvn = NULL; nvn = dir->head; while (nvn && (strcmp(name, nvn->name) > 0)) { pvn = nvn; nvn = nvn->next; } vn->next = nvn; if (nvn) nvn->prev = vn; vn->prev = pvn; if (pvn) pvn->next = vn; else dir->head = vn; vn->head = NULL; vn->symlink = NULL; atomic_add(&ns->vnnum, 1); InsertSL(ns->skiplist, vn); *vnp = vn; return 0;error2: if (vn) free(vn); if (buf) free(buf);error1: return err;}static intdo_unlink(nspace *ns, vnode *dir, const char *name, bool isdir){ int err; vnode *vn; LOCK(ns->lock); if (!MY_S_ISDIR(dir->mode)) { err = ENOTDIR; goto error1; } /* can't delete '..' and '.' */ if (!strcmp(name, "..") || !strcmp(name, ".")) { err = EINVAL; goto error1; } /* lookup the name in the directory */ vn = dir->head; while (vn) { if (!strcmp(vn->name, name)) break; vn = vn->next; } /* if it was not found, report an error. */ if (!vn) { err = ENOENT; goto error1; } /* ensure it is of the appropriate type. */ if (isdir && !(vn->mode & MY_S_IFDIR)) { err = ENOTDIR; goto error1; } if (!isdir && (vn->mode & MY_S_IFDIR)) { err = EISDIR; goto error1; } /* make sure it is not the root */ if (vn == vn->ns->root) { err = EBUSY; goto error1; } /* if it is a directory, make sure it is empty */ if (MY_S_ISDIR(vn->mode) && vn->head) { err = ENOTEMPTY; goto error1; } err = get_vnode(ns->nsid, vn->vnid, (void *)&vn); if (err) goto error1; err = remove_vnode(ns->nsid, vn->vnid); if (err) goto error1; if (vn->prev) vn->prev->next = vn->next; else vn->parent->head = vn->next; if (vn->next) vn->next->prev = vn->prev; vn->prev = vn->next = NULL; vn->removed = TRUE; dir->mtime = time(NULL); put_vnode(ns->nsid, vn->vnid); UNLOCK(ns->lock); return 0;error1: UNLOCK(ns->lock); return err;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -