Whamcloud - gitweb
Branch: HEAD
[fs/lustre-release.git] / libsysio / src / init.c
index 38d0794..ce253cc 100644 (file)
 #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"
@@ -93,7 +81,7 @@ _sysio_init()
 {
        int     err;
 #ifdef WITH_SOCKETS
-       int     _sysio_sockets_init(void);
+        int     _sysio_sockets_init(void);
 #endif
 
        err = _sysio_ioctx_init();
@@ -115,9 +103,9 @@ _sysio_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;
@@ -162,8 +150,8 @@ _sysio_shutdown()
  * 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,
@@ -212,15 +200,20 @@ get_token(const char *buf,
  *
  * 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;
@@ -228,15 +221,20 @@ get_args(char *buf, struct named_argument *vec)
                }
                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;
@@ -271,7 +269,7 @@ static int
 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 */
@@ -291,27 +289,27 @@ do_creat(char *args)
        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))
@@ -323,9 +321,10 @@ do_creat(char *args)
                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)
@@ -340,12 +339,13 @@ do_creat(char *args)
                        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)
@@ -360,18 +360,19 @@ do_creat(char *args)
                        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);
@@ -380,7 +381,7 @@ do_creat(char *args)
                        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;
@@ -388,13 +389,12 @@ do_creat(char *args)
                        /*
                         * 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,
@@ -433,7 +433,7 @@ static int
 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 */
@@ -445,35 +445,46 @@ do_mnt(char *args)
        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
  *
@@ -483,7 +494,7 @@ static int
 do_cd(char *args) 
 {
        size_t  len;
-       struct named_argument v[] = {
+       struct option_value_info v[] = {
                { "dir",        NULL },                 /* directory */
                { NULL,         NULL }
        };
@@ -491,12 +502,12 @@ do_cd(char *args)
        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);
@@ -504,6 +515,7 @@ do_cd(char *args)
                P_RELE(pno);
        return err;
 }
+#endif
 
 /*
  * Does a chmod
@@ -514,7 +526,7 @@ static int
 do_chmd(char *args)
 {
        size_t  len;
-       struct named_argument v[] = {
+       struct option_value_info v[] = {
                { "src",        NULL },                 /* path */
                { "pm",         NULL },                 /* perms */
                { NULL,         NULL }
@@ -526,10 +538,10 @@ do_chmd(char *args)
        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) ||
@@ -540,7 +552,7 @@ do_chmd(char *args)
 
        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);
@@ -549,6 +561,83 @@ do_chmd(char *args)
        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.
  *
@@ -561,16 +650,20 @@ do_command(char *buf)
        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;
 }
@@ -580,15 +673,23 @@ do_command(char *buf)
  * 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;
@@ -608,7 +709,12 @@ _sysio_boot(const char *buf)
                /*
                 * 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;
@@ -621,5 +727,10 @@ _sysio_boot(const char *buf)
                        break;
        }
        free(tok);
+#if DEFER_INIT_CWD
+       if (err)
+               return err;
+       _sysio_init_cwd = path;
+#endif
        return err;
 }