#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <sys/queue.h>
-#include <sys/uio.h>
-
-#include <sys/stat.h>
#include <fcntl.h>
+#include <sys/uio.h>
+#include <sys/queue.h>
+#include "xtio.h"
#include "sysio.h"
#include "inode.h"
#include "fs.h"
#include "mount.h"
#include "file.h"
#include "dev.h"
-#include "xtio.h"
#ifdef STDFD_DEV
#include "stdfd.h"
#endif
/*
- * The namespace assembly buffer passes args with a `name'=`value'
- * syntax. We use the following to record that in various
- * routines below.
- */
-struct named_argument {
- const char *name; /* arg name */
- char *value; /* arg value */
-};
-
-/*
* White space characters.
*/
#define IGNORE_WHITE " \t\r\n"
{
int err;
#ifdef WITH_SOCKETS
- int _sysio_sockets_init(void);
+ int _sysio_sockets_init(void);
#endif
err = _sysio_ioctx_init();
goto error;
#endif
#ifdef WITH_SOCKETS
- err = _sysio_sockets_init();
- if (err)
- goto error;
+ err = _sysio_sockets_init();
+ if (err)
+ goto error;
#endif
goto out;
* or NUL character is success.
*
*/
-static const char *
-get_token(const char *buf,
+const char *
+_sysio_get_token(const char *buf,
int accepts,
const char *delim,
const char *ignore,
*
* NB: Alters the passed buffer.
*/
-static char *
-get_args(char *buf, struct named_argument *vec)
+char *
+_sysio_get_args(char *buf, struct option_value_info *vec)
{
char *nxt;
char *name, *value;
- struct named_argument *v;
+ struct option_value_info *v;
for (;;) {
- nxt = (char *)get_token(buf, 1, "=,", IGNORE_WHITE, name = buf);
+ nxt =
+ (char *)_sysio_get_token(buf,
+ 1,
+ "=,",
+ IGNORE_WHITE,
+ name = buf);
if (!nxt ||
(nxt != buf && *name == '\0' && buf + strlen(buf) == nxt)) {
buf = NULL;
}
if (*name == '\0')
break;
- buf = (char *)get_token(nxt, 1, ",", IGNORE_WHITE, value = nxt);
+ buf =
+ (char *)_sysio_get_token(nxt,
+ 1,
+ ",",
+ IGNORE_WHITE,
+ value = nxt);
if (*value == '\0')
value = NULL;
- for (v = vec; v->name; v++)
- if (strcmp(v->name, name) == 0)
+ for (v = vec; v->ovi_name; v++)
+ if (strcmp(v->ovi_name, name) == 0)
break;
- if (!v->name)
+ if (!v->ovi_name)
return NULL;
- v->value = value;
+ v->ovi_value = value;
}
return buf;
do_creat(char *args)
{
size_t len;
- struct named_argument v[] = {
+ struct option_value_info v[] = {
{ "ft", NULL }, /* file type */
{ "nm", NULL }, /* name */
{ "pm", NULL }, /* permissions */
int err;
len = strlen(args);
- if (get_args(args, v) - args != (ssize_t )len ||
- !(v[0].value &&
- v[1].value &&
- v[2].value))
+ 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].value, (char **)&cp, 0);
+ 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].value) {
- owner = strtol(v[3].value, (char **)&cp, 0);
+ 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].value) {
- group = strtol(v[4].value, (char **)&cp, 0);
+ 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 -ENOENT;
err = 0;
mode = perms;
- if (strcmp(v[0].value, "dir") == 0) {
+ if (strcmp(v[0].ovi_value, "dir") == 0) {
INTENT_INIT(&intent, INT_CREAT, &mode, 0);
- err = _sysio_namei(dir, v[1].value, ND_NEGOK, &intent, &pno);
+ err =
+ _sysio_namei(dir, v[1].ovi_value, ND_NEGOK, &intent, &pno);
if (err)
return err;
if (pno->p_base->pb_ino)
err = (*ino->i_ops.inop_mkdir)(pno, mode);
}
P_RELE(pno);
- } else if (strcmp(v[0].value, "chr") == 0) {
- if (!(v[5].value && parse_mm(v[5].value, &dev) == 0))
+ } else if (strcmp(v[0].ovi_value, "chr") == 0) {
+ if (!(v[5].ovi_value && parse_mm(v[5].ovi_value, &dev) == 0))
return -EINVAL;
mode |= S_IFCHR;
INTENT_INIT(&intent, INT_CREAT, &mode, 0);
- err = _sysio_namei(dir, v[1].value, ND_NEGOK, &intent, &pno);
+ err =
+ _sysio_namei(dir, v[1].ovi_value, ND_NEGOK, &intent, &pno);
if (err)
return err;
if (pno->p_base->pb_ino)
err = (*ino->i_ops.inop_mknod)(pno, mode, dev);
}
P_RELE(pno);
- } else if (strcmp(v[0].value, "blk") == 0) {
+ } else if (strcmp(v[0].ovi_value, "blk") == 0) {
/*
* We don't support block special files yet.
*/
return -EINVAL;
- } else if (strcmp(v[0].value, "file") == 0) {
+ } else if (strcmp(v[0].ovi_value, "file") == 0) {
int i;
struct inode *ino;
i = O_CREAT|O_EXCL;
INTENT_INIT(&intent, INT_CREAT, &mode, &i);
- err = _sysio_namei(dir, v[1].value, ND_NEGOK, &intent, &pno);
+ err =
+ _sysio_namei(dir, v[1].ovi_value, ND_NEGOK, &intent, &pno);
if (err)
return err;
err = _sysio_open(pno, O_CREAT|O_EXCL, mode);
return err;
}
ino = pno->p_base->pb_ino;
- if (!err && v[6].value) {
+ if (!err && v[6].ovi_value) {
struct iovec iovec;
struct intnl_xtvec xtvec;
struct ioctx io_context;
/*
* Deposit optional file content.
*/
- iovec.iov_base = v[6].value;
- iovec.iov_len = strlen(v[6].value);
+ 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,
- (ioid_t )&io_context,
1,
ino,
&iovec, 1,
do_mnt(char *args)
{
size_t len;
- struct named_argument v[] = {
+ struct option_value_info v[] = {
{ "dev", NULL }, /* source (type:dev) */
{ "dir", NULL }, /* target dir */
{ "fl", NULL }, /* flags */
struct pnode *dir;
len = strlen(args);
- if (get_args(args, v) - args != (ssize_t )len ||
- !(v[0].value && v[1].value))
+ if (_sysio_get_args(args, v) - args != (ssize_t )len ||
+ !(v[0].ovi_value && v[1].ovi_value))
return -EINVAL;
- ty = (char *)get_token(v[0].value, 1, ":", "", name = v[0].value);
+ ty =
+ (char *)_sysio_get_token(v[0].ovi_value,
+ 1,
+ ":",
+ "",
+ name = v[0].ovi_value);
flags = 0;
- if (v[2].value) {
+ if (v[2].ovi_value) {
char *cp;
/*
* Optional flags.
*/
- flags = strtoul(v[2].value, &cp, 0);
+ flags = strtoul(v[2].ovi_value, &cp, 0);
if (*cp || (flags == ULONG_MAX && errno == ERANGE))
return -EINVAL;
}
- if (strlen(v[1].value) == 1 && v[1].value[0] == PATH_SEPARATOR) {
+ 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].value);
+ 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].value, name, flags, v[3].value);
+ return _sysio_mount(dir,
+ ty,
+ v[1].ovi_value,
+ name,
+ flags,
+ v[3].ovi_value);
}
+#if 0
/*
* Chdir
*
do_cd(char *args)
{
size_t len;
- struct named_argument v[] = {
+ struct option_value_info v[] = {
{ "dir", NULL }, /* directory */
{ NULL, NULL }
};
struct pnode *dir, *pno;
len = strlen(args);
- if (get_args(args, v) - args != (ssize_t )len || !v[0].value)
+ if (_sysio_get_args(args, v) - args != (ssize_t )len || !v[0].ovi_value)
return -EINVAL;
if (!(dir = _sysio_cwd) && !(dir = _sysio_root))
return -ENOENT;
- err = _sysio_namei(dir, v[0].value, 0, NULL, &pno);
+ err = _sysio_namei(dir, v[0].ovi_value, 0, NULL, &pno);
if (err)
return err;
err = _sysio_p_chdir(pno);
P_RELE(pno);
return err;
}
+#endif
/*
* Does a chmod
do_chmd(char *args)
{
size_t len;
- struct named_argument v[] = {
+ struct option_value_info v[] = {
{ "src", NULL }, /* path */
{ "pm", NULL }, /* perms */
{ NULL, NULL }
struct pnode *dir, *pno;
len = strlen(args);
- if (get_args(args, v) - args != (ssize_t )len ||
- !(v[0].value && v[1].value))
+ if (_sysio_get_args(args, v) - args != (ssize_t )len ||
+ !(v[0].ovi_value && v[1].ovi_value))
return -EINVAL;
- perms = strtol(v[1].value, &cp, 0);
+ perms = strtol(v[1].ovi_value, &cp, 0);
if (*cp ||
perms < 0 ||
(perms == LONG_MAX && errno == ERANGE) ||
if (!(dir = _sysio_cwd) && !(dir = _sysio_root))
return -ENOENT;
- err = _sysio_namei(dir, v[0].value, 0, NULL, &pno);
+ err = _sysio_namei(dir, v[0].ovi_value, 0, NULL, &pno);
if (err)
return err;
err = _sysio_setattr(pno, pno->p_base->pb_ino, SETATTR_MODE, &stbuf);
return err;
}
+static int
+do_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;
+
+/*
+ * Check if long overflows integer range.
+ */
+#if LONG_MAX <= INT_MAX
+#define _irecheck(_l, _e) \
+ ((_l) == LONG_MAX && (_e) == ERANGE)
+#else
+#define _irecheck(_l, _e) \
+ ((_l) > INT_MAX)
+#endif
+
+ 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, 0, &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;
+
+#undef _irecheck
+}
+
/*
* Execute the given cmd.
*
char *args, *cmd;
len = strlen(buf);
- args = (char *)get_token(buf, 1, ",", IGNORE_WHITE, cmd = 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;
}
* commands
*/
int
-_sysio_boot(const char *buf)
+_sysio_boot(const char *buf
+#if DEFER_INIT_CWD
+ , const char *path
+#endif
+ )
{
char c, *tok;
+ ssize_t len;
int err;
+ if (!buf)
+ buf = "";
/*
* Allocate token buffer.
*/
- tok = malloc(strlen(buf));
+ len = strlen(buf);
+ tok = malloc(len ? len : 1);
if (!tok)
return -ENOMEM;
err = 0;
/*
* Get the command.
*/
- buf = (char *)get_token(buf + 1, 0, "}", IGNORE_WHITE, tok);
+ buf =
+ (char *)_sysio_get_token(buf + 1,
+ 0,
+ "}",
+ IGNORE_WHITE,
+ tok);
if (!buf) {
err = -EINVAL;
break;
break;
}
free(tok);
+#if DEFER_INIT_CWD
+ if (err)
+ return err;
+ _sysio_init_cwd = path;
+#endif
return err;
}