2 * This Cplant(TM) source code is the property of Sandia National
5 * This Cplant(TM) source code is copyrighted by Sandia National
8 * The redistribution of this Cplant(TM) source code is subject to the
9 * terms of the GNU Lesser General Public License
10 * (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html)
12 * Cplant(TM) Copyright 1998-2004 Sandia Corporation.
13 * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive
14 * license for use of this work by or on behalf of the US Government.
15 * Export of this program may require a license from the United States
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License as published by the Free Software Foundation; either
23 * version 2.1 of the License, or (at your option) any later version.
25 * This library is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
28 * Lesser General Public License for more details.
30 * You should have received a copy of the GNU Lesser General Public
31 * License along with this library; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
34 * Questions or comments about this library should be sent to:
37 * Sandia National Laboratories, New Mexico
39 * Albuquerque, NM 87185-1110
52 #include <sys/types.h>
56 #include <sys/queue.h>
71 * The namespace assembly buffer passes args with a `name'=`value'
72 * syntax. We use the following to record that in various
75 struct named_argument {
76 const char *name; /* arg name */
77 char *value; /* arg value */
81 * White space characters.
83 #define IGNORE_WHITE " \t\r\n"
86 * Sysio library initialization. Must be called before anything else in the
94 int _sysio_sockets_init(void);
97 err = _sysio_ioctx_init();
100 err = _sysio_i_init();
103 err = _sysio_mount_init();
107 err = _sysio_dev_init();
111 err = _sysio_stdfd_init();
116 err = _sysio_sockets_init();
126 * Unlike all other _sysio routines, this one returns with errno
127 * set. It also returns the error, as usual.
133 * Sysio library shutdown.
139 if (!(_sysio_fd_close_all() == 0 &&
140 _sysio_unmount_all() == 0))
144 _sysio_fd_shutdown();
146 _sysio_fssw_shutdown();
151 * (kind of)Duplicates strtok function.
153 * Given a buffer, returns the longest string
154 * that does not contain any delim characters. Will
155 * remove ws and any characters in the ignore string.
158 * The parameter controlling acceptance controls whether a positive
159 * match for some delimiter be made or not. If set, then either a delimiter
160 * or NUL character is success.
164 get_token(const char *buf,
174 * Find the first occurance of delim, recording how many
175 * characters lead up to it. Ignore indicated characters.
178 while ((c = *buf) != '\0') {
190 if (strchr(delim, c) != NULL) {
194 if (strchr(ignore, c) != NULL)
203 *tbuf = '\0'; /* NUL term */
208 * Parse and record named arguments given as `name = value', comma-separated
211 * NB: Alters the passed buffer.
214 get_args(char *buf, struct named_argument *vec)
218 struct named_argument *v;
221 nxt = (char *)get_token(buf, 1, "=,", IGNORE_WHITE, name = buf);
223 (nxt != buf && *name == '\0' && buf + strlen(buf) == nxt)) {
229 buf = (char *)get_token(nxt, 1, ",", IGNORE_WHITE, value = nxt);
232 for (v = vec; v->name; v++)
233 if (strcmp(v->name, name) == 0)
244 parse_mm(const char *s, dev_t *devp)
250 ul = strtoul(s, &cp, 0);
251 if (*cp != '+' || ul > USHRT_MAX)
254 s = (const char *)++cp;
255 ul = strtoul(s, &cp, 0);
256 if (*cp != '\0' || ul > USHRT_MAX)
264 * Performs the creat command for the namespace assembly
266 * NB: Alters the passed buffer.
272 struct named_argument v[] = {
273 { "ft", NULL }, /* file type */
274 { "nm", NULL }, /* name */
275 { "pm", NULL }, /* permissions */
276 { "ow", NULL }, /* owner */
277 { "gr", NULL }, /* group */
278 { "mm", NULL }, /* major + minor */
279 { "str", NULL }, /* file data */
285 struct pnode *dir, *pno;
287 struct intent intent;
292 if (get_args(args, v) - args != (ssize_t )len ||
297 perms = strtol(v[2].value, (char **)&cp, 0);
300 (perms == LONG_MAX && errno == ERANGE) ||
301 ((unsigned)perms & ~07777))
304 owner = strtol(v[3].value, (char **)&cp, 0);
306 ((owner == LONG_MIN || owner == LONG_MAX)
312 group = strtol(v[4].value, (char **)&cp, 0);
314 ((group == LONG_MIN || group == LONG_MAX) &&
320 if (!(dir = _sysio_cwd) && !(dir = _sysio_root))
324 if (strcmp(v[0].value, "dir") == 0) {
325 INTENT_INIT(&intent, INT_CREAT, &mode, 0);
326 err = _sysio_namei(dir, v[1].value, ND_NEGOK, &intent, &pno);
329 if (pno->p_base->pb_ino)
331 else if (IS_RDONLY(pno->p_parent,
332 pno->p_parent->p_base->pb_ino))
337 ino = pno->p_parent->p_base->pb_ino;
338 err = (*ino->i_ops.inop_mkdir)(pno, mode);
341 } else if (strcmp(v[0].value, "chr") == 0) {
342 if (!(v[5].value && parse_mm(v[5].value, &dev) == 0))
345 INTENT_INIT(&intent, INT_CREAT, &mode, 0);
346 err = _sysio_namei(dir, v[1].value, ND_NEGOK, &intent, &pno);
349 if (pno->p_base->pb_ino)
351 else if (IS_RDONLY(pno->p_parent,
352 pno->p_parent->p_base->pb_ino))
357 ino = pno->p_parent->p_base->pb_ino;
358 err = (*ino->i_ops.inop_mknod)(pno, mode, dev);
361 } else if (strcmp(v[0].value, "blk") == 0) {
363 * We don't support block special files yet.
366 } else if (strcmp(v[0].value, "file") == 0) {
371 INTENT_INIT(&intent, INT_CREAT, &mode, &i);
372 err = _sysio_namei(dir, v[1].value, ND_NEGOK, &intent, &pno);
375 err = _sysio_open(pno, O_CREAT|O_EXCL, mode);
380 ino = pno->p_base->pb_ino;
381 if (!err && v[6].value) {
383 struct intnl_xtvec xtvec;
384 struct ioctx io_context;
387 * Deposit optional file content.
389 iovec.iov_base = v[6].value;
390 iovec.iov_len = strlen(v[6].value);
392 xtvec.xtv_len = iovec.iov_len;
393 IOCTX_INIT(&io_context,
399 _sysio_ioctx_enter(&io_context);
401 (*ino->i_ops.inop_write)(pno->p_base->pb_ino,
406 cc = _sysio_ioctx_wait(&io_context);
409 else if ((size_t )cc != iovec.iov_len)
410 err = -EIO; /* huh? */
412 _sysio_ioctx_complete(&io_context);
414 i = (*ino->i_ops.inop_close)(ino);
427 * NB: The passed buffer is altered.
433 struct named_argument v[] = {
434 { "dev", NULL }, /* source (type:dev) */
435 { "dir", NULL }, /* target dir */
436 { "fl", NULL }, /* flags */
437 { "da", NULL }, /* mount data */
445 if (get_args(args, v) - args != (ssize_t )len ||
446 !(v[0].value && v[1].value))
448 ty = (char *)get_token(v[0].value, 1, ":", "", name = v[0].value);
456 flags = strtoul(v[2].value, &cp, 0);
457 if (*cp || (flags == ULONG_MAX && errno == ERANGE))
461 if (strlen(v[1].value) == 1 && v[1].value[0] == PATH_SEPARATOR) {
463 * Aha! It's root they want. Have to do that special.
465 return _sysio_mount_root(ty, name, flags, v[3].value);
468 if (!(dir = _sysio_cwd) && !(dir = _sysio_root))
470 return _sysio_mount(dir, ty, v[1].value, name, flags, v[3].value);
477 * NB: Alters the passed buffer.
483 struct named_argument v[] = {
484 { "dir", NULL }, /* directory */
488 struct pnode *dir, *pno;
491 if (get_args(args, v) - args != (ssize_t )len || !v[0].value)
494 if (!(dir = _sysio_cwd) && !(dir = _sysio_root))
496 err = _sysio_namei(dir, v[0].value, 0, NULL, &pno);
499 err = _sysio_p_chdir(pno);
508 * NB: Alters passed buffer.
514 struct named_argument v[] = {
515 { "src", NULL }, /* path */
516 { "pm", NULL }, /* perms */
521 struct intnl_stat stbuf;
523 struct pnode *dir, *pno;
526 if (get_args(args, v) - args != (ssize_t )len ||
527 !(v[0].value && v[1].value))
529 perms = strtol(v[1].value, &cp, 0);
532 (perms == LONG_MAX && errno == ERANGE) ||
533 ((unsigned)perms & ~07777))
535 (void )memset(&stbuf, 0, sizeof(stbuf));
536 stbuf.st_mode = (mode_t)perms;
538 if (!(dir = _sysio_cwd) && !(dir = _sysio_root))
540 err = _sysio_namei(dir, v[0].value, 0, NULL, &pno);
543 err = _sysio_setattr(pno, pno->p_base->pb_ino, SETATTR_MODE, &stbuf);
553 struct named_argument v[] = {
554 { "nm", NULL }, /* path */
555 { "fd", NULL }, /* fildes */
556 { "m", NULL }, /* mode */
562 struct pnode *dir, *pno;
563 struct intent intent;
568 if (get_args(args, v) - args != (ssize_t )len ||
569 !(v[0].value && v[1].value && v[2].value))
571 fd = strtol(v[1].value, (char **)&cp, 0);
573 (((fd == LONG_MIN || fd == LONG_MAX) && errno == ERANGE)) ||
576 m = strtoul(v[1].value, (char **)&cp, 0);
578 (m == LONG_MAX && errno == ERANGE))
580 m &= O_RDONLY|O_WRONLY|O_RDWR;
582 if (!(dir = _sysio_cwd) && !(dir = _sysio_root))
584 INTENT_INIT(&intent, INT_OPEN, &m, NULL);
586 err = _sysio_namei(dir, v[0].value, 0, &intent, &pno);
591 err = _sysio_open(pno, m, 0);
594 fil = _sysio_fnew(pno->p_base->pb_ino, m);
599 err = _sysio_fd_set(fil, fd, 1);
613 * Execute the given cmd.
615 * NB: Buf is altered.
618 do_command(char *buf)
624 args = (char *)get_token(buf, 1, ",", IGNORE_WHITE, cmd = buf);
626 if (strcmp("creat", cmd) == 0)
627 return do_creat(args);
628 if (strcmp("mnt", cmd) == 0)
630 if (strcmp("cd", cmd) == 0)
632 if (strcmp("chmd", cmd) == 0)
633 return do_chmd(args);
634 if (strcmp("open", cmd) == 0)
635 return do_open(args);
641 * Given a command sequence buffer, parse it and run the given
645 _sysio_boot(const char *buf)
651 * Allocate token buffer.
653 tok = malloc(strlen(buf));
659 * Discard leading white space.
661 while ((c = *buf) != '\0' &&
662 !(c == '{' || strchr(IGNORE_WHITE, c) == NULL))
673 buf = (char *)get_token(buf + 1, 0, "}", IGNORE_WHITE, tok);
681 err = do_command(tok);