📄 init.c
字号:
/* * This Cplant(TM) source code is the property of Sandia National * Laboratories. * * This Cplant(TM) source code is copyrighted by Sandia National * Laboratories. * * The redistribution of this Cplant(TM) source code is subject to the * terms of the GNU Lesser General Public License * (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html) * * Cplant(TM) Copyright 1998-2006 Sandia Corporation. * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive * license for use of this work by or on behalf of the US Government. * Export of this program may require a license from the United States * Government. *//* * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Questions or comments about this library should be sent to: * * Lee Ward * Sandia National Laboratories, New Mexico * P.O. Box 5800 * Albuquerque, NM 87185-1110 * * lee@sandia.gov */#ifdef __linux__#define _BSD_SOURCE#endif#ifdef SYSIO_TRACING#include <stdio.h>#endif#include <stdlib.h>#if defined(_BSD_SOURCE) || defined(SYSIO_TRACING)#include <sys/syscall.h>#endif#include <unistd.h>#include <string.h>#include <errno.h>#ifdef SYSIO_TRACING#include <stdarg.h>#endif#include <limits.h>#include <assert.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <sys/uio.h>#include <sys/queue.h>#include "sysio.h"#include "xtio.h"#ifdef SYSIO_TRACING#include "native.h"#endif#include "inode.h"#include "fs.h"#include "mount.h"#include "file.h"#include "dev.h"#ifdef STDFD_DEV#include "stdfd.h"#endif#ifdef SYSIO_TRACING/* * Tracing callback record. */struct trace_callback { TAILQ_ENTRY(trace_callback) links; /* trace list links */ void (*f)(const char *file, /* callback function */ const char *func, int line, void *data); void *data; /* callback data */ void (*destructor)(void *data); /* data destructor */};/* * Initialize a tracing callback record. */#define TCB_INIT(__tcb, __f, __d, __destroy) \ do { \ (__tcb)->f = (__f); \ (__tcb)->data = (__d); \ (__tcb)->destructor = (__destroy); \ } while (0);/* * Trace queue head record. */TAILQ_HEAD(trace_q, trace_callback);/* * The entry and exit queue heads, and queue pointers. */static struct trace_q _sysio_entry_trace_head;void *_sysio_entry_trace_q = &_sysio_entry_trace_head;static struct trace_q _sysio_exit_trace_head;void *_sysio_exit_trace_q = &_sysio_exit_trace_head;#endif/* * White space characters. */#define IGNORE_WHITE " \t\r\n"/* * 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/* * In sysio_init we'll allow simple comments, strings outside {} * delimited by COMMENT_INTRO, and '\n' or '\0' */#define COMMENT_INTRO '#'/* * In sysio_init we'll allow simple comments, strings outside {} * delimited by COMMENT_INTRO, and '\n' or '\0' */#define COMMENT_INTRO '#'/* * Sysio library initialization. Must be called before anything else in the * library. */int_sysio_init(){ int err;#ifdef WITH_SOCKETS extern int _sysio_sockets_init(void);#endif#ifdef SYSIO_TRACING /* * Initialize tracing callback queues. */ TAILQ_INIT(&_sysio_entry_trace_head); TAILQ_INIT(&_sysio_exit_trace_head);#endif err = _sysio_ioctx_init(); if (err) goto error; err = _sysio_i_init(); if (err) goto error; err = _sysio_mount_init(); if (err) goto error; err = _sysio_dev_init(); if (err) goto error;#ifdef STDFD_DEV err = _sysio_stdfd_init(); if (err) goto error;#endif#ifdef WITH_SOCKETS err = _sysio_sockets_init(); if (err) goto error;#endif goto out;error: errno = -err;out: /* * Unlike all other _sysio routines, this one returns with errno * set. It also returns the error, as usual. */ return err;}/* * Sysio library shutdown. */void_sysio_shutdown(){ if (!(_sysio_fd_close_all() == 0 && _sysio_unmount_all() == 0)) abort();#ifdef ZERO_SUM_MEMORY _sysio_fd_shutdown(); _sysio_i_shutdown(); _sysio_fssw_shutdown(); _sysio_access_shutdown();#ifdef SYSIO_TRACING { struct trace_callback *tcb; /* * Empty the trace queues and free the entries. */ while ((tcb = _sysio_entry_trace_head.tqh_first) != NULL) _sysio_remove_trace(&_sysio_entry_trace_head, tcb); while ((tcb = _sysio_exit_trace_head.tqh_first) != NULL) _sysio_remove_trace(&_sysio_exit_trace_head, tcb); }#endif#endif}#ifdef SYSIO_TRACING#if !(defined(_HAVE_ASPRINTF) && _HAVE_ASPRINTF)/* * Print a string to allocated memory. */static intvasprintf(char **strp, const char *fmt, va_list ap){ size_t siz; int oerrno; char *s; va_list aq; int n; siz = 50; oerrno = errno; if (!(s = malloc(siz))) { errno = oerrno; return -1; } for (;;) { va_copy(aq, ap); n = vsnprintf (s, siz, fmt, aq); va_end(aq); if (n > -1 && (size_t )n < siz) break; if (n > -1) /* glibc 2.1 */ siz = n+1; /* precise */ else /* glibc 2.0 */ siz *= 2; /* twice the old */ if (!(s = realloc (s, siz))) break; } *strp = s; errno = oerrno; return n;}#if 0static intasprintf(char **strp, const char *fmt, ...){ va_list ap; int n; va_start(ap, fmt); n = vasprintf(strp, fmt, ap); va_end(ap); return n;}#endif#endif /* !(defined(_HAVE_ASPRINTF) && _HAVE_ASPRINTF) */static void_sysio_cwrite(const char *buf, size_t len){ int oerrno; oerrno = errno; (void )syscall(SYSIO_SYS_write, STDERR_FILENO, buf, len); errno = oerrno;}/* * Console printf. */void_sysio_cprintf(const char *fmt, ...){ va_list ap; int len; char *buf; va_start(ap, fmt); buf = NULL; len = vasprintf(&buf, fmt, ap); va_end(ap); if (len < 0) return; _sysio_cwrite(buf, len); free(buf);}/* * Register a trace callback. * * The pointer to the trace record is returned. */void *_sysio_register_trace(void *q, void (*f)(const char *file, const char *func, int line, void *data), void *data, void (*destructor)(void *data)){ struct trace_callback *tcb; tcb = malloc(sizeof(struct trace_callback)); if (!tcb) return NULL; TCB_INIT(tcb, f, data, destructor); TAILQ_INSERT_TAIL((struct trace_q *)q, tcb, links); return tcb;}/* * Remove a registered trace callback. */void_sysio_remove_trace(void *q, void *p){ struct trace_callback *tcb; tcb = (struct trace_callback *)p; if (tcb->destructor) (*tcb->destructor)(tcb->data); TAILQ_REMOVE((struct trace_q *)q, tcb, links); free(tcb);}void/* * Run a trace queue, making all the callbacks. */_sysio_run_trace_q(void *q, const char *file, const char *func, int line){ struct trace_callback *tcb; tcb = ((struct trace_q *)q)->tqh_first; while (tcb) { (*tcb->f)(file, func, line, tcb->data); tcb = tcb->links.tqe_next; }}static void_sysio_trace_entry(const char *file __IS_UNUSED, const char *func, int line __IS_UNUSED, void *data __IS_UNUSED){ _sysio_cprintf("+ENTER+ %s\n", func);}static void_sysio_trace_exit(const char *file __IS_UNUSED, const char *func, int line __IS_UNUSED, void *data __IS_UNUSED){ _sysio_cprintf("+EXIT+ %s\n", func);}#endif /* defined(SYSIO_TRACING) *//* * (kind of)Duplicates strtok function. * * Given a buffer, returns the longest string * that does not contain any delim characters. Will * remove ws and any characters in the ignore string. * Returns the token. * * The parameter controlling acceptance controls whether a positive * match for some delimiter be made or not. If set, then either a delimiter * or NUL character is success. * */const char *_sysio_get_token(const char *buf, int accepts, const char *delim, const char *ignore, char *tbuf){ char c; int escape, quote; /* * Find the first occurance of delim, recording how many * characters lead up to it. Ignore indicated characters. */ escape = quote = 0; while ((c = *buf) != '\0') { buf++; if (!escape) { if (c == '\\') { escape = 1; continue; } if (c == '\"') { quote ^= 1; continue; } if (!quote) { if (strchr(delim, c) != NULL) { accepts = 1; break; } if (strchr(ignore, c) != NULL) continue; } } else escape = 0; *tbuf++ = c; } if (!accepts) return NULL; *tbuf = '\0'; /* NUL term */ return buf;}/* * Parse and record named arguments given as `name = value', comma-separated * pairs. * * NB: Alters the passed buffer. */char *_sysio_get_args(char *buf, struct option_value_info *vec){ char *nxt; char *name, *value; struct option_value_info *v; for (;;) { nxt = (char *)_sysio_get_token(buf, 1, "=,", IGNORE_WHITE, name = buf); if (!nxt || (nxt != buf && *name == '\0' && buf + strlen(buf) == nxt)) { buf = NULL; break; } if (*name == '\0') break; buf = (char *)_sysio_get_token(nxt, 1, ",", IGNORE_WHITE, value = nxt); if (*value == '\0') value = NULL; for (v = vec; v->ovi_name; v++) if (strcmp(v->ovi_name, name) == 0) break; if (!v->ovi_name) return NULL; v->ovi_value = value; } return buf;}static intparse_mm(const char *s, dev_t *devp){ unsigned long ul; char *cp; dev_t dev; ul = strtoul(s, &cp, 0); if (*cp != '+' || ul > USHRT_MAX) return -EINVAL; dev = ul << 16; s = (const char *)++cp; ul = strtoul(s, &cp, 0); if (*cp != '\0' || ul > USHRT_MAX) return -EINVAL; dev |= ul & 0xffff; *devp = dev; return 0;}/* * Performs the creat command for the namespace assembly * * NB: Alters the passed buffer. */static int do_creat(char *args) { size_t len; struct option_value_info v[] = { { "ft", NULL }, /* file type */ { "nm", NULL }, /* name */ { "pm", NULL }, /* permissions */ { "ow", NULL }, /* owner */ { "gr", NULL }, /* group */ { "mm", NULL }, /* major + minor */ { "str", NULL }, /* file data */ { NULL, NULL } }; const char *cp; long perms; long owner, group; struct pnode *dir, *pno; mode_t mode; struct intent intent; dev_t dev; int err; enum { CREATE_DIR = 1,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -