/* ------------------------------------------------------------------------ $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 #include #include #include #include #include #include #include #include #include #include /* * 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; }