summaryrefslogtreecommitdiffstats
path: root/c/src/libmisc/rootfs/mkrootfs.c
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>2001-09-19 17:29:42 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>2001-09-19 17:29:42 +0000
commitd34d2e695714fcaf3827ac0132d19f5781b986d0 (patch)
tree801edfaeeb00baf764e51a2c48b85e7dcbc7b4c3 /c/src/libmisc/rootfs/mkrootfs.c
parent5dfa8c1e4450e09b3d2d1f0fc7ea3a8f32e09a4e (diff)
downloadrtems-d34d2e695714fcaf3827ac0132d19f5781b986d0.tar.bz2
2001-09-19 Chris Johns <ccj@acm.org>
* Added support for populating the initial "root" filesystem with information obtained via the DHCP response. * rootfs: New directory. * rootfs/.cvsignore, rootfs/Makefile.am, rootfs/mkrootfs.c, rootfs/mkrootfs.h: New files. * configure.in, Makefile.am: Modified to reflect addition.
Diffstat (limited to 'c/src/libmisc/rootfs/mkrootfs.c')
-rw-r--r--c/src/libmisc/rootfs/mkrootfs.c348
1 files changed, 348 insertions, 0 deletions
diff --git a/c/src/libmisc/rootfs/mkrootfs.c b/c/src/libmisc/rootfs/mkrootfs.c
new file mode 100644
index 0000000000..d8c6301b6a
--- /dev/null
+++ b/c/src/libmisc/rootfs/mkrootfs.c
@@ -0,0 +1,348 @@
+/*
+ ------------------------------------------------------------------------
+ $Id$
+ ------------------------------------------------------------------------
+
+ Copyright Cybertec Pty Ltd, 2000
+ All rights reserved Cybertec Pty Ltd, 2000
+
+ COPYRIGHT (c) 1989-1998.
+ On-Line Applications Research Corporation (OAR).
+ Copyright assigned to U.S. Government, 1994.
+
+ The license and distribution terms for this file may be
+ found in the file LICENSE in this distribution or at
+
+ http://www.OARcorp.com/rtems/license.html.
+
+ This software with is provided ``as is'' and with NO WARRANTY.
+
+ ------------------------------------------------------------------------
+
+ Set of helpers when creating a root file system. The root filesystem
+ in RTEMS is the In Memory Filesystem (IMFS). We could copy an exiting
+ filesystem to here, how-ever a number of files can have target
+ specific initialisation info which we need to write.
+
+ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <rtems/mkrootfs.h>
+
+/*
+ * A table a list of names and their modes.
+ */
+
+typedef struct rtems_rootfs_dir_table
+{
+ const char *name;
+ int mode;
+} rtems_rootfs_dir_table;
+
+/*
+ * Table of directorys to make.
+ */
+
+static const rtems_rootfs_dir_table default_directories[] =
+{
+ { "/bin", S_IFDIR | S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH },
+ { "/etc", S_IFDIR | S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH },
+ { "/dev", S_IFDIR | S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH },
+ { "/usr/bin", S_IFDIR | S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH }
+};
+
+#define MKFILE_MODE (S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH)
+#define MKDIR_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
+
+/*
+ * Build a path. Taken from the BSD `mkdir' command.
+ */
+
+int
+rtems_rootfs_mkdir (const char *path_orig, mode_t omode)
+{
+ struct stat sb;
+ mode_t numask, oumask;
+ int first, last, retval;
+ char path[128];
+ char *p = path;
+
+ if (strlen (path_orig) >= sizeof path)
+ {
+ printf ("root fs: mkdir path too long `%s'\n", path);
+ return -1;
+ }
+
+ strcpy (path, path_orig);
+ oumask = 0;
+ retval = 0;
+ if (p[0] == '/') /* Skip leading '/'. */
+ ++p;
+ for (first = 1, last = 0; !last ; ++p)
+ {
+ if (p[0] == '\0')
+ last = 1;
+ else if (p[0] != '/')
+ continue;
+ *p = '\0';
+ if (p[1] == '\0')
+ last = 1;
+ if (first)
+ {
+ /*
+ * POSIX 1003.2:
+ * For each dir operand that does not name an existing
+ * directory, effects equivalent to those cased by the
+ * following command shall occcur:
+ *
+ * mkdir -p -m $(umask -S),u+wx $(dirname dir) &&
+ * mkdir [-m mode] dir
+ *
+ * We change the user's umask and then restore it,
+ * instead of doing chmod's.
+ */
+ oumask = umask(0);
+ numask = oumask & ~(S_IWUSR | S_IXUSR);
+ umask(numask);
+ first = 0;
+ }
+ if (last)
+ umask(oumask);
+ if (stat(path, &sb))
+ {
+ if (errno != ENOENT)
+ {
+ printf ("root fs: error stat'ing path `%s', %s\n",
+ path, strerror (errno));
+ retval = 1;
+ break;
+ }
+ if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0)
+ {
+ printf ("root fs: error building path `%s', %s\n",
+ path, strerror (errno));
+ retval = 1;
+ break;
+ }
+ }
+ else if ((sb.st_mode & S_IFMT) != S_IFDIR)
+ {
+ if (last)
+ errno = EEXIST;
+ else
+ errno = ENOTDIR;
+ printf ("root fs: path `%s' contains a file, %s\n",
+ path, strerror (errno));
+ retval = 1;
+ break;
+ }
+ if (!last)
+ *p = '/';
+ }
+ if (!first && !last)
+ umask(oumask);
+ return retval;
+}
+
+/*
+ * Create enough files to support the networking stack.
+ * Points to a table of strings.
+ */
+
+int
+rtems_rootfs_file_append (const char *file,
+ mode_t omode,
+ const int line_cnt,
+ const char **lines)
+{
+ struct stat sb;
+ int fd;
+ int i;
+
+ /*
+ * See is a file exists. If it does not, create the
+ * file and the path to the file.
+ */
+
+ fd = -1;
+
+ if (stat(file, &sb))
+ {
+ if (errno == ENOENT)
+ {
+ /*
+ * Get the path to the file if one exists and create the
+ * path. If it exists nothing happens.
+ */
+
+ int i = strlen (file);
+
+ while (i)
+ {
+ if (file[i] == '/')
+ {
+ char path[128];
+
+ if (i >= sizeof path)
+ {
+ printf ("root fs, path too long `%s'\n", file);
+ return -1;
+ }
+
+ strncpy (path, file, i);
+ path[i] = '\0';
+
+ if (rtems_rootfs_mkdir (path, MKDIR_MODE))
+ return -1;
+ break;
+ }
+ i--;
+ }
+
+ if ((fd = open (file, O_CREAT | O_APPEND | O_WRONLY, omode)) < 0)
+ {
+ printf ("root fs, cannot create file `%s' : %s\n",
+ file, strerror (errno));
+ return -1;
+ }
+ }
+ }
+
+ if (fd < 0)
+ {
+ if ((fd = open (file, O_APPEND | O_WRONLY)) < 0)
+ {
+ printf ("root fs, cannot open file `%s' : %s\n",
+ file, strerror (errno));
+ return -1;
+ }
+ }
+
+ for (i = 0; i < line_cnt; i++)
+ {
+ int len = strlen (lines[i]);
+
+ if (len)
+ {
+ if (write (fd, lines[i], strlen (lines[i])) < 0)
+ {
+ close (fd);
+ printf ("root fs, cannot write to `%s' : %s\n",
+ file, strerror (errno));
+ return -1;
+ }
+ }
+ }
+
+ return close (fd);
+}
+
+/*
+ * Write hosts record.
+ */
+
+int
+rtems_rootfs_append_host_rec (unsigned long cip,
+ const char *cname,
+ const char *dname)
+{
+ char buf[128];
+ char *bufp = buf;
+ const char *bufl[1];
+ struct in_addr ip;
+
+ ip.s_addr = cip;
+
+ if (cname && strlen (cname))
+ {
+ snprintf (bufp, sizeof (buf), "%s\t\t%s", inet_ntoa (ip), cname);
+ bufp += strlen (buf);
+
+ if (dname && strlen (dname))
+ {
+ snprintf (bufp, sizeof (buf), "\t\t%s.%s", cname, dname);
+ bufp += strlen (buf);
+ }
+
+ strcat (buf, "\n");
+
+ bufl[0] = buf;
+
+ if (rtems_rootfs_file_append ("/etc/hosts", MKFILE_MODE, 1, bufl) < 0)
+ return -1;
+ }
+ else
+ {
+ printf ("rootfs hosts rec append, no cname supplied\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Create a root file system.
+ */
+
+int
+rtems_create_root_fs ()
+{
+ const char *lines[1];
+ int i;
+
+ /*
+ * Create the directories.
+ */
+
+ for (i = 0;
+ i < (sizeof (default_directories) / sizeof (rtems_rootfs_dir_table));
+ i++)
+ if (rtems_rootfs_mkdir (default_directories[i].name,
+ default_directories[i].mode))
+ return -1;
+
+ /*
+ * /etc/passwd, /etc/group
+ * Maybe needed by some tools.
+ */
+
+ lines[0] = "root::0:0:root:/root:/bin/sh\n";
+
+ if (rtems_rootfs_file_append ("/etc/passwd", MKFILE_MODE, 1, lines))
+ return -1;
+
+ lines[0] = "root::0:root\n";
+
+ if (rtems_rootfs_file_append ("/etc/group", MKFILE_MODE, 1, lines))
+ return -1;
+
+ /*
+ * The TCP/IP stack likes this one. If DNS does not work
+ * use the host file.
+ */
+
+ lines[0] = "hosts,bind\n";
+
+ if (rtems_rootfs_file_append ("/etc/host.conf", MKFILE_MODE, 1, lines))
+ return -1;
+
+ /*
+ * Create a `/etc/hosts' file.
+ */
+
+ if (rtems_rootfs_append_host_rec (0x7f000001, "localhost", "localdomain"))
+ return -1;
+
+ return 0;
+}
+