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>
54 #include <sys/queue.h>
73 * The namespace assembly buffer passes args with a `name'=`value'
74 * syntax. We use the following to record that in various
77 struct named_argument {
78 const char *name; /* arg name */
79 char *value; /* arg value */
83 * White space characters.
85 #define IGNORE_WHITE " \t\r\n"
88 * Sysio library initialization. Must be called before anything else in the
96 int _sysio_sockets_init(void);
99 err = _sysio_ioctx_init();
102 err = _sysio_i_init();
105 err = _sysio_mount_init();
109 err = _sysio_dev_init();
113 err = _sysio_stdfd_init();
118 err = _sysio_sockets_init();
128 * Unlike all other _sysio routines, this one returns with errno
129 * set. It also returns the error, as usual.
135 * Sysio library shutdown.
141 if (!(_sysio_fd_close_all() == 0 &&
142 _sysio_unmount_all() == 0))
146 _sysio_fd_shutdown();
148 _sysio_fssw_shutdown();
153 * (kind of)Duplicates strtok function.
155 * Given a buffer, returns the longest string
156 * that does not contain any delim characters. Will
157 * remove ws and any characters in the ignore string.
160 * The parameter controlling acceptance controls whether a positive
161 * match for some delimiter be made or not. If set, then either a delimiter
162 * or NUL character is success.
166 get_token(const char *buf,
176 * Find the first occurance of delim, recording how many
177 * characters lead up to it. Ignore indicated characters.
180 while ((c = *buf) != '\0') {
192 if (strchr(delim, c) != NULL) {
196 if (strchr(ignore, c) != NULL)
205 *tbuf = '\0'; /* NUL term */
210 * Parse and record named arguments given as `name = value', comma-separated
213 * NB: Alters the passed buffer.
216 get_args(char *buf, struct named_argument *vec)
220 struct named_argument *v;
223 nxt = (char *)get_token(buf, 1, "=,", IGNORE_WHITE, name = buf);
225 (nxt != buf && *name == '\0' && buf + strlen(buf) == nxt)) {
231 buf = (char *)get_token(nxt, 1, ",", IGNORE_WHITE, value = nxt);
234 for (v = vec; v->name; v++)
235 if (strcmp(v->name, name) == 0)
246 parse_mm(const char *s, dev_t *devp)
252 ul = strtoul(s, &cp, 0);
253 if (*cp != '+' || ul > USHRT_MAX)
256 s = (const char *)++cp;
257 ul = strtoul(s, &cp, 0);
258 if (*cp != '\0' || ul > USHRT_MAX)
266 * Performs the creat command for the namespace assembly
268 * NB: Alters the passed buffer.
274 struct named_argument v[] = {
275 { "ft", NULL }, /* file type */
276 { "nm", NULL }, /* name */
277 { "pm", NULL }, /* permissions */
278 { "ow", NULL }, /* owner */
279 { "gr", NULL }, /* group */
280 { "mm", NULL }, /* major + minor */
281 { "str", NULL }, /* file data */
287 struct pnode *dir, *pno;
289 struct intent intent;
294 if (get_args(args, v) - args != (ssize_t )len ||
299 perms = strtol(v[2].value, (char **)&cp, 0);
302 (perms == LONG_MAX && errno == ERANGE) ||
303 ((unsigned)perms & ~07777))
306 owner = strtol(v[3].value, (char **)&cp, 0);
308 ((owner == LONG_MIN || owner == LONG_MAX)
314 group = strtol(v[4].value, (char **)&cp, 0);
316 ((group == LONG_MIN || group == LONG_MAX) &&
322 if (!(dir = _sysio_cwd) && !(dir = _sysio_root))
326 if (strcmp(v[0].value, "dir") == 0) {
327 INTENT_INIT(&intent, INT_CREAT, &mode, 0);
328 err = _sysio_namei(dir, v[1].value, ND_NEGOK, &intent, &pno);
331 if (pno->p_base->pb_ino)
333 else if (IS_RDONLY(pno->p_parent,
334 pno->p_parent->p_base->pb_ino))
339 ino = pno->p_parent->p_base->pb_ino;
340 err = (*ino->i_ops.inop_mkdir)(pno, mode);
343 } else if (strcmp(v[0].value, "chr") == 0) {
344 if (!(v[5].value && parse_mm(v[5].value, &dev) == 0))
347 INTENT_INIT(&intent, INT_CREAT, &mode, 0);
348 err = _sysio_namei(dir, v[1].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].value, "blk") == 0) {
365 * We don't support block special files yet.
368 } else if (strcmp(v[0].value, "file") == 0) {
373 INTENT_INIT(&intent, INT_CREAT, &mode, &i);
374 err = _sysio_namei(dir, v[1].value, ND_NEGOK, &intent, &pno);
377 err = _sysio_open(pno, O_CREAT|O_EXCL, mode);
382 ino = pno->p_base->pb_ino;
383 if (!err && v[6].value) {
385 struct intnl_xtvec xtvec;
386 struct ioctx io_context;
389 * Deposit optional file content.
391 iovec.iov_base = v[6].value;
392 iovec.iov_len = strlen(v[6].value);
394 xtvec.xtv_len = iovec.iov_len;
395 IOCTX_INIT(&io_context,
397 (ioid_t )&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 named_argument v[] = {
437 { "dev", NULL }, /* source (type:dev) */
438 { "dir", NULL }, /* target dir */
439 { "fl", NULL }, /* flags */
440 { "da", NULL }, /* mount data */
448 if (get_args(args, v) - args != (ssize_t )len ||
449 !(v[0].value && v[1].value))
451 ty = (char *)get_token(v[0].value, 1, ":", "", name = v[0].value);
459 flags = strtoul(v[2].value, &cp, 0);
460 if (*cp || (flags == ULONG_MAX && errno == ERANGE))
464 if (strlen(v[1].value) == 1 && v[1].value[0] == PATH_SEPARATOR) {
466 * Aha! It's root they want. Have to do that special.
468 return _sysio_mount_root(ty, name, flags, v[3].value);
471 if (!(dir = _sysio_cwd) && !(dir = _sysio_root))
473 return _sysio_mount(dir, ty, v[1].value, name, flags, v[3].value);
480 * NB: Alters the passed buffer.
486 struct named_argument v[] = {
487 { "dir", NULL }, /* directory */
491 struct pnode *dir, *pno;
494 if (get_args(args, v) - args != (ssize_t )len || !v[0].value)
497 if (!(dir = _sysio_cwd) && !(dir = _sysio_root))
499 err = _sysio_namei(dir, v[0].value, 0, NULL, &pno);
502 err = _sysio_p_chdir(pno);
511 * NB: Alters passed buffer.
517 struct named_argument v[] = {
518 { "src", NULL }, /* path */
519 { "pm", NULL }, /* perms */
524 struct intnl_stat stbuf;
526 struct pnode *dir, *pno;
529 if (get_args(args, v) - args != (ssize_t )len ||
530 !(v[0].value && v[1].value))
532 perms = strtol(v[1].value, &cp, 0);
535 (perms == LONG_MAX && errno == ERANGE) ||
536 ((unsigned)perms & ~07777))
538 (void )memset(&stbuf, 0, sizeof(stbuf));
539 stbuf.st_mode = (mode_t)perms;
541 if (!(dir = _sysio_cwd) && !(dir = _sysio_root))
543 err = _sysio_namei(dir, v[0].value, 0, NULL, &pno);
546 err = _sysio_setattr(pno, pno->p_base->pb_ino, SETATTR_MODE, &stbuf);
553 * Execute the given cmd.
555 * NB: Buf is altered.
558 do_command(char *buf)
564 args = (char *)get_token(buf, 1, ",", IGNORE_WHITE, cmd = buf);
566 if (strcmp("creat", cmd) == 0)
567 return do_creat(args);
568 if (strcmp("mnt", cmd) == 0)
570 if (strcmp("cd", cmd) == 0)
572 if (strcmp("chmd", cmd) == 0)
573 return do_chmd(args);
579 * Given a command sequence buffer, parse it and run the given
583 _sysio_boot(const char *buf)
589 * Allocate token buffer.
591 tok = malloc(strlen(buf));
597 * Discard leading white space.
599 while ((c = *buf) != '\0' &&
600 !(c == '{' || strchr(IGNORE_WHITE, c) == NULL))
611 buf = (char *)get_token(buf + 1, 0, "}", IGNORE_WHITE, tok);
619 err = do_command(tok);