📄 init.c
字号:
CREATE_CHR = 2, CREATE_BLK = 3, CREATE_FILE = 4 } op; int intent_mode; struct inode *ino; int i; len = strlen(args); if (_sysio_get_args(args, v) - args != (ssize_t )len || !(v[0].ovi_value && v[1].ovi_value && v[2].ovi_value)) return -EINVAL; perms = strtol(v[2].ovi_value, (char **)&cp, 0); if (*cp || perms < 0 || (perms == LONG_MAX && errno == ERANGE) || ((unsigned)perms & ~07777)) return -EINVAL; if (v[3].ovi_value) { owner = strtol(v[3].ovi_value, (char **)&cp, 0); if (*cp || ((owner == LONG_MIN || owner == LONG_MAX) && errno == ERANGE)) return -EINVAL; } else owner = getuid(); if (v[4].ovi_value) { group = strtol(v[4].ovi_value, (char **)&cp, 0); if (*cp || ((group == LONG_MIN || group == LONG_MAX) && errno == ERANGE)) return -EINVAL; } else group = getegid(); if (!(dir = _sysio_cwd) && !(dir = _sysio_root)) return -ENOENT; /* * Init, get the operation, setup the intent. */ err = 0; mode = perms; op = 0; if (strcmp(v[0].ovi_value, "dir") == 0) { op = CREATE_DIR; INTENT_INIT(&intent, INT_CREAT, &mode, NULL); } else if (strcmp(v[0].ovi_value, "chr") == 0) { op = CREATE_CHR; mode |= S_IFCHR; INTENT_INIT(&intent, INT_CREAT, &mode, NULL); if (!(v[5].ovi_value && parse_mm(v[5].ovi_value, &dev) == 0)) err = -EINVAL; } else if (strcmp(v[0].ovi_value, "blk") == 0) { op = CREATE_BLK; mode |= S_IFBLK; INTENT_INIT(&intent, INT_CREAT, &mode, NULL); if (!(v[5].ovi_value && parse_mm(v[5].ovi_value, &dev) == 0)) err = -EINVAL; } else if (strcmp(v[0].ovi_value, "file") == 0) { op = CREATE_FILE; intent_mode = O_CREAT|O_EXCL; INTENT_INIT(&intent, INT_CREAT, &mode, &intent_mode); } else err = -EINVAL; if (err) return err; /* * Lookup the given path. */ err = _sysio_namei(dir, v[1].ovi_value, ND_NEGOK|ND_NOPERMCHECK, &intent, &pno); if (err) return err; /* * Perform. */ switch (op) { case CREATE_DIR: err = _sysio_mkdir(pno, mode); break; case CREATE_CHR: case CREATE_BLK: err = _sysio_mknod(pno, mode, dev); break; case CREATE_FILE: err = _sysio_open(pno, O_CREAT|O_EXCL, mode); if (err) break; ino = pno->p_base->pb_ino; if (v[6].ovi_value) { struct iovec iovec; struct intnl_xtvec xtvec; struct ioctx io_context; /* * Deposit optional file content. */ iovec.iov_base = v[6].ovi_value; iovec.iov_len = strlen(v[6].ovi_value); xtvec.xtv_off = 0; xtvec.xtv_len = iovec.iov_len; IOCTX_INIT(&io_context, 1, 1, ino, &iovec, 1, &xtvec, 1); _sysio_ioctx_enter(&io_context); err = (*ino->i_ops.inop_write)(pno->p_base->pb_ino, &io_context); if (!err) { ssize_t cc; cc = _sysio_ioctx_wait(&io_context); if (cc < 0) err = cc; else if ((size_t )cc != iovec.iov_len) err = -EIO; /* huh? */ } else _sysio_ioctx_complete(&io_context); } i = (*ino->i_ops.inop_close)(ino); if (!err) err = i; break; default: abort(); } P_RELE(pno); return err;}/* * Do mount. * * NB: The passed buffer is altered. */static int do_mnt(char *args) { size_t len; struct option_value_info v[] = { { "dev", NULL }, /* source (type:dev) */ { "dir", NULL }, /* target dir */ { "fl", NULL }, /* flags */ { "da", NULL }, /* mount data */ { NULL, NULL } }; char *ty, *name; unsigned long flags; struct pnode *dir; len = strlen(args); if (_sysio_get_args(args, v) - args != (ssize_t )len || !(v[0].ovi_value && v[1].ovi_value)) return -EINVAL; ty = (char *)_sysio_get_token(v[0].ovi_value, 1, ":", "", name = v[0].ovi_value); flags = 0; if (v[2].ovi_value) { char *cp; /* * Optional flags. */ flags = strtoul(v[2].ovi_value, &cp, 0); if (*cp || (flags == ULONG_MAX && errno == ERANGE)) return -EINVAL; } if (strlen(v[1].ovi_value) == 1 && v[1].ovi_value[0] == PATH_SEPARATOR) { /* * Aha! It's root they want. Have to do that special. */ return _sysio_mount_root(ty, name, flags, v[3].ovi_value); } if (!(dir = _sysio_cwd) && !(dir = _sysio_root)) return -ENOENT; return _sysio_mount(dir, ty, v[1].ovi_value, name, flags, v[3].ovi_value);}#if 0/* * Chdir * * NB: Alters the passed buffer. */static int do_cd(char *args) { size_t len; struct option_value_info v[] = { { "dir", NULL }, /* directory */ { NULL, NULL } }; int err; struct pnode *dir, *pno; len = strlen(args); if (_sysio_get_args(args, v) - args != (ssize_t )len || !v[0].ovi_value) return -EINVAL; if (!(dir = _sysio_cwd) && !(dir = _sysio_root)) { /* * We have no namespace yet. They really need to give us * something to work with. */ return -ENOENT; } err = _sysio_namei(dir, v[0].ovi_value, 0, NULL, &pno); if (err) return err; err = _sysio_p_chdir(pno); if (err) P_RELE(pno); return err;}#endif/* * Does a chmod * * NB: Alters passed buffer. */static int do_chmd(char *args){ size_t len; struct option_value_info v[] = { { "src", NULL }, /* path */ { "pm", NULL }, /* perms */ { NULL, NULL } }; long perms; char *cp; struct intnl_stat stbuf; int err; struct pnode *dir, *pno; len = strlen(args); if (_sysio_get_args(args, v) - args != (ssize_t )len || !(v[0].ovi_value && v[1].ovi_value)) return -EINVAL; perms = strtol(v[1].ovi_value, &cp, 0); if (*cp || perms < 0 || (perms == LONG_MAX && errno == ERANGE) || ((unsigned)perms & ~07777)) return -EINVAL; (void )memset(&stbuf, 0, sizeof(stbuf)); stbuf.st_mode = (mode_t)perms; if (!(dir = _sysio_cwd) && !(dir = _sysio_root)) return -ENOENT; err = _sysio_namei(dir, v[0].ovi_value, ND_NOPERMCHECK, NULL, &pno); if (err) return err; err = _sysio_setattr(pno, pno->p_base->pb_ino, SETATTR_MODE, &stbuf); P_RELE(pno); return err;}static intdo_open(char *args){ size_t len; struct option_value_info v[] = { { "nm", NULL }, /* path */ { "fd", NULL }, /* fildes */ { "m", NULL }, /* mode */ { NULL, NULL } }; char *cp; long l; int fd; unsigned long ul; mode_t m; struct pnode *dir, *pno; struct intent intent; int err; struct file *fil; len = strlen(args); if (_sysio_get_args(args, v) - args != (ssize_t )len || !(v[0].ovi_value && v[1].ovi_value && v[2].ovi_value)) return -EINVAL; l = strtol(v[1].ovi_value, (char **)&cp, 0); if (*cp || l < 0 || _irecheck(l, errno)) return -EINVAL; fd = (int )l; ul = strtoul(v[1].ovi_value, (char **)&cp, 0); if (*cp || (ul == ULONG_MAX && errno == ERANGE)) return -EINVAL; m = (mode_t )ul & (O_RDONLY|O_WRONLY|O_RDWR); if (!(dir = _sysio_cwd) && !(dir = _sysio_root)) return -ENOENT; INTENT_INIT(&intent, INT_OPEN, &m, NULL); pno = NULL; err = _sysio_namei(dir, v[0].ovi_value, ND_NOPERMCHECK, &intent, &pno); if (err) return err; fil = NULL; do { err = _sysio_open(pno, m, 0); if (err) break; fil = _sysio_fnew(pno->p_base->pb_ino, m); if (!fil) { err = -ENOMEM; break; } err = _sysio_fd_set(fil, fd, 1); if (err < 0) break; P_RELE(pno); return 0; } while (0); if (fil) F_RELE(fil); if (pno) P_RELE(pno); return err;}/* * Execute the given cmd. * * NB: Buf is altered. */static int do_command(char *buf){ size_t len; char *args, *cmd; len = strlen(buf); args = (char *)_sysio_get_token(buf, 1, ",", IGNORE_WHITE, cmd = buf); if (args) { if (strcmp("creat", cmd) == 0) return do_creat(args); if (strcmp("mnt", cmd) == 0) return do_mnt(args);#if 0 if (strcmp("cd", cmd) == 0) return do_cd(args);#endif if (strcmp("chmd", cmd) == 0) return do_chmd(args); if (strcmp("open", cmd) == 0) return do_open(args); } return -EINVAL;}#ifdef SYSIO_TRACING/* * Set/Unset tracing. */static int_sysio_boot_tracing(const char *arg){ long l; char *cp; static struct trace_callback *entcb = NULL, *exitcb = NULL; l = 0; if (arg) { l = strtol(arg, (char **)&cp, 0); if (*cp || !(l == 0 || l == 1)) return -EINVAL; } if (l) { if (entcb == NULL) entcb = _sysio_register_trace(_sysio_entry_trace_q, _sysio_trace_entry, NULL, NULL); if (entcb == NULL) return -errno; if (exitcb == NULL) exitcb = _sysio_register_trace(_sysio_exit_trace_q, _sysio_trace_exit, NULL, NULL); if (exitcb == NULL) return -errno; } else { if (entcb != NULL) _sysio_remove_trace(_sysio_entry_trace_q, entcb); entcb = NULL; if (exitcb != NULL) _sysio_remove_trace(_sysio_exit_trace_q, exitcb); exitcb = NULL; } return 0;}#endif/* * Initialize the namespace. */static int_sysio_boot_namespace(const char *arg){ char c, *tok; ssize_t len; int err; unsigned count; /* * Allocate token buffer. */ len = strlen(arg); tok = malloc(len ? len : 1); if (!tok) return -ENOMEM; err = 0; count = 0; while (1) { /* * Discard leading white space. */ while ((c = *arg) != '\0' && strchr(IGNORE_WHITE, c)) arg++; if (COMMENT_INTRO == c) { /* * Discard comment. */ while (*arg && (*arg != '\n')) { ++arg; } continue; } if (c == '\0') break; if (c != '{') { err = -EINVAL; break; } /* * Get the command. */ *tok = '\0'; arg = (char *)_sysio_get_token(arg + 1, 0, "}", IGNORE_WHITE, tok); if (!arg) { err = -EINVAL; break; } count++; /* * Perform. */ err = do_command(tok); if (err) break; }#ifdef SYSIO_TRACING if (err) _sysio_cprintf("+NS init+ failed at expr %u (last = %s): %s\n", count, tok && *tok ? tok : "NULL", strerror(-err));#endif free(tok); return err;}#ifdef DEFER_INIT_CWD/* * Set deferred initial working directory. */static int_sysio_boot_cwd(const char *arg){ _sysio_init_cwd = arg; return 0;}#endif/* * Given an identifier and it's arguments, perform optional initializations. */int_sysio_boot(const char *opt, const char *arg){ struct option_value_info vec[] = {#ifdef SYSIO_TRACING { "trace", NULL }, /* tracing? */#endif { "namespace", NULL }, /* init namespace? */#ifdef DEFER_INIT_CWD { "cwd", NULL }, /* init working dir */#endif { NULL, NULL } }; struct option_value_info *v; unsigned u; static int (*f[])(const char *) = {#ifdef SYSIO_TRACING _sysio_boot_tracing,#endif _sysio_boot_namespace,#ifdef DEFER_INIT_CWD _sysio_boot_cwd,#endif NULL /* can't happen */ }; for (v = vec, u = 0; v->ovi_name; v++, u++) if (strcmp(v->ovi_name, opt) == 0) break; if (!v->ovi_name) return -EINVAL; return (*f[u])(arg);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -