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 * White space characters.
73 #define IGNORE_WHITE " \t\r\n"
76 * Sysio library initialization. Must be called before anything else in the
84 int _sysio_sockets_init(void);
87 err = _sysio_ioctx_init();
90 err = _sysio_i_init();
93 err = _sysio_mount_init();
97 err = _sysio_dev_init();
101 err = _sysio_stdfd_init();
106 err = _sysio_sockets_init();
116 * Unlike all other _sysio routines, this one returns with errno
117 * set. It also returns the error, as usual.
123 * Sysio library shutdown.
129 if (!(_sysio_fd_close_all() == 0 &&
130 _sysio_unmount_all() == 0))
134 _sysio_fd_shutdown();
136 _sysio_fssw_shutdown();
141 * (kind of)Duplicates strtok function.
143 * Given a buffer, returns the longest string
144 * that does not contain any delim characters. Will
145 * remove ws and any characters in the ignore string.
148 * The parameter controlling acceptance controls whether a positive
149 * match for some delimiter be made or not. If set, then either a delimiter
150 * or NUL character is success.
154 _sysio_get_token(const char *buf,
164 * Find the first occurance of delim, recording how many
165 * characters lead up to it. Ignore indicated characters.
168 while ((c = *buf) != '\0') {
180 if (strchr(delim, c) != NULL) {
184 if (strchr(ignore, c) != NULL)
193 *tbuf = '\0'; /* NUL term */
198 * Parse and record named arguments given as `name = value', comma-separated
201 * NB: Alters the passed buffer.
204 _sysio_get_args(char *buf, struct option_value_info *vec)
208 struct option_value_info *v;
212 (char *)_sysio_get_token(buf,
218 (nxt != buf && *name == '\0' && buf + strlen(buf) == nxt)) {
225 (char *)_sysio_get_token(nxt,
232 for (v = vec; v->ovi_name; v++)
233 if (strcmp(v->ovi_name, name) == 0)
237 v->ovi_value = value;
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 option_value_info 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 (_sysio_get_args(args, v) - args != (ssize_t )len ||
297 perms = strtol(v[2].ovi_value, (char **)&cp, 0);
300 (perms == LONG_MAX && errno == ERANGE) ||
301 ((unsigned)perms & ~07777))
303 if (v[3].ovi_value) {
304 owner = strtol(v[3].ovi_value, (char **)&cp, 0);
306 ((owner == LONG_MIN || owner == LONG_MAX)
311 if (v[4].ovi_value) {
312 group = strtol(v[4].ovi_value, (char **)&cp, 0);
314 ((group == LONG_MIN || group == LONG_MAX) &&
320 if (!(dir = _sysio_cwd) && !(dir = _sysio_root))
324 if (strcmp(v[0].ovi_value, "dir") == 0) {
325 INTENT_INIT(&intent, INT_CREAT, &mode, 0);
327 _sysio_namei(dir, v[1].ovi_value, ND_NEGOK, &intent, &pno);
330 if (pno->p_base->pb_ino)
332 else if (IS_RDONLY(pno->p_parent,
333 pno->p_parent->p_base->pb_ino))
338 ino = pno->p_parent->p_base->pb_ino;
339 err = (*ino->i_ops.inop_mkdir)(pno, mode);
342 } else if (strcmp(v[0].ovi_value, "chr") == 0) {
343 if (!(v[5].ovi_value && parse_mm(v[5].ovi_value, &dev) == 0))
346 INTENT_INIT(&intent, INT_CREAT, &mode, 0);
348 _sysio_namei(dir, v[1].ovi_value, ND_NEGOK, &intent, &pno);
351 if (pno->p_base->pb_ino)
353 else if (IS_RDONLY(pno->p_parent,
354 pno->p_parent->p_base->pb_ino))
359 ino = pno->p_parent->p_base->pb_ino;
360 err = (*ino->i_ops.inop_mknod)(pno, mode, dev);
363 } else if (strcmp(v[0].ovi_value, "blk") == 0) {
365 * We don't support block special files yet.
368 } else if (strcmp(v[0].ovi_value, "file") == 0) {
373 INTENT_INIT(&intent, INT_CREAT, &mode, &i);
375 _sysio_namei(dir, v[1].ovi_value, ND_NEGOK, &intent, &pno);
378 err = _sysio_open(pno, O_CREAT|O_EXCL, mode);
383 ino = pno->p_base->pb_ino;
384 if (!err && v[6].ovi_value) {
386 struct intnl_xtvec xtvec;
387 struct ioctx io_context;
390 * Deposit optional file content.
392 iovec.iov_base = v[6].ovi_value;
393 iovec.iov_len = strlen(v[6].ovi_value);
395 xtvec.xtv_len = iovec.iov_len;
396 IOCTX_INIT(&io_context,
402 _sysio_ioctx_enter(&io_context);
404 (*ino->i_ops.inop_write)(pno->p_base->pb_ino,
409 cc = _sysio_ioctx_wait(&io_context);
412 else if ((size_t )cc != iovec.iov_len)
413 err = -EIO; /* huh? */
415 _sysio_ioctx_complete(&io_context);
417 i = (*ino->i_ops.inop_close)(ino);
430 * NB: The passed buffer is altered.
436 struct option_value_info v[] = {
437 { "dev", NULL }, /* source (type:dev) */
438 { "dir", NULL }, /* target dir */
439 { "fl", NULL }, /* flags */
440 { "da", NULL }, /* mount data */
448 if (_sysio_get_args(args, v) - args != (ssize_t )len ||
449 !(v[0].ovi_value && v[1].ovi_value))
452 (char *)_sysio_get_token(v[0].ovi_value,
456 name = v[0].ovi_value);
458 if (v[2].ovi_value) {
464 flags = strtoul(v[2].ovi_value, &cp, 0);
465 if (*cp || (flags == ULONG_MAX && errno == ERANGE))
469 if (strlen(v[1].ovi_value) == 1 && v[1].ovi_value[0] == PATH_SEPARATOR) {
471 * Aha! It's root they want. Have to do that special.
473 return _sysio_mount_root(ty, name, flags, v[3].ovi_value);
476 if (!(dir = _sysio_cwd) && !(dir = _sysio_root))
478 return _sysio_mount(dir,
491 * NB: Alters the passed buffer.
497 struct option_value_info v[] = {
498 { "dir", NULL }, /* directory */
502 struct pnode *dir, *pno;
505 if (_sysio_get_args(args, v) - args != (ssize_t )len || !v[0].ovi_value)
508 if (!(dir = _sysio_cwd) && !(dir = _sysio_root))
510 err = _sysio_namei(dir, v[0].ovi_value, 0, NULL, &pno);
513 err = _sysio_p_chdir(pno);
523 * NB: Alters passed buffer.
529 struct option_value_info v[] = {
530 { "src", NULL }, /* path */
531 { "pm", NULL }, /* perms */
536 struct intnl_stat stbuf;
538 struct pnode *dir, *pno;
541 if (_sysio_get_args(args, v) - args != (ssize_t )len ||
542 !(v[0].ovi_value && v[1].ovi_value))
544 perms = strtol(v[1].ovi_value, &cp, 0);
547 (perms == LONG_MAX && errno == ERANGE) ||
548 ((unsigned)perms & ~07777))
550 (void )memset(&stbuf, 0, sizeof(stbuf));
551 stbuf.st_mode = (mode_t)perms;
553 if (!(dir = _sysio_cwd) && !(dir = _sysio_root))
555 err = _sysio_namei(dir, v[0].ovi_value, 0, NULL, &pno);
558 err = _sysio_setattr(pno, pno->p_base->pb_ino, SETATTR_MODE, &stbuf);
568 struct option_value_info v[] = {
569 { "nm", NULL }, /* path */
570 { "fd", NULL }, /* fildes */
571 { "m", NULL }, /* mode */
579 struct pnode *dir, *pno;
580 struct intent intent;
585 * Check if long overflows integer range.
587 #if LONG_MAX <= INT_MAX
588 #define _irecheck(_l, _e) \
589 ((_l) == LONG_MAX && (_e) == ERANGE)
591 #define _irecheck(_l, _e) \
596 if (_sysio_get_args(args, v) - args != (ssize_t )len ||
597 !(v[0].ovi_value && v[1].ovi_value && v[2].ovi_value))
599 l = strtol(v[1].ovi_value, (char **)&cp, 0);
600 if (*cp || l < 0 || _irecheck(l, errno))
603 ul = strtoul(v[1].ovi_value, (char **)&cp, 0);
605 (ul == ULONG_MAX && errno == ERANGE))
607 m = (mode_t )ul & (O_RDONLY|O_WRONLY|O_RDWR);
609 if (!(dir = _sysio_cwd) && !(dir = _sysio_root))
611 INTENT_INIT(&intent, INT_OPEN, &m, NULL);
613 err = _sysio_namei(dir, v[0].ovi_value, 0, &intent, &pno);
618 err = _sysio_open(pno, m, 0);
621 fil = _sysio_fnew(pno->p_base->pb_ino, m);
626 err = _sysio_fd_set(fil, fd, 1);
642 * Execute the given cmd.
644 * NB: Buf is altered.
647 do_command(char *buf)
653 args = (char *)_sysio_get_token(buf, 1, ",", IGNORE_WHITE, cmd = buf);
655 if (strcmp("creat", cmd) == 0)
656 return do_creat(args);
657 if (strcmp("mnt", cmd) == 0)
660 if (strcmp("cd", cmd) == 0)
663 if (strcmp("chmd", cmd) == 0)
664 return do_chmd(args);
665 if (strcmp("open", cmd) == 0)
666 return do_open(args);
672 * Given a command sequence buffer, parse it and run the given
676 _sysio_boot(const char *buf
689 * Allocate token buffer.
692 tok = malloc(len ? len : 1);
698 * Discard leading white space.
700 while ((c = *buf) != '\0' &&
701 !(c == '{' || strchr(IGNORE_WHITE, c) == NULL))
713 (char *)_sysio_get_token(buf + 1,
725 err = do_command(tok);
733 _sysio_init_cwd = path;