source: rtems/c/src/exec/libnetworking/rtems/mkrootfs.c @ d34d2e69

4.104.114.84.95
Last change on this file since d34d2e69 was d34d2e69, checked in by Joel Sherrill <joel.sherrill@…>, on 09/19/01 at 17:29:42

2001-09-19 Chris Johns <ccj@…>

  • 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.
  • Property mode set to 100644
File size: 7.6 KB
Line 
1/*
2  ------------------------------------------------------------------------
3  $Id$
4  ------------------------------------------------------------------------
5 
6  Copyright Cybertec Pty Ltd, 2000
7  All rights reserved Cybertec Pty Ltd, 2000
8
9  COPYRIGHT (c) 1989-1998.
10  On-Line Applications Research Corporation (OAR).
11  Copyright assigned to U.S. Government, 1994.
12
13  The license and distribution terms for this file may be
14  found in the file LICENSE in this distribution or at
15 
16  http://www.OARcorp.com/rtems/license.html.
17
18  This software with is provided ``as is'' and with NO WARRANTY.
19
20  ------------------------------------------------------------------------
21
22  Set of helpers when creating a root file system. The root filesystem
23  in RTEMS is the In Memory Filesystem (IMFS). We could copy an exiting
24  filesystem to here, how-ever a number of files can have target
25  specific initialisation info which we need to write.
26 
27 */
28
29#include <errno.h>
30#include <stdio.h>
31#include <string.h>
32#include <sys/stat.h>
33#include <sys/types.h>
34#include <fcntl.h>
35#include <unistd.h>
36#include <sys/socket.h>
37#include <netinet/in.h>
38#include <arpa/inet.h>
39
40#include <rtems/mkrootfs.h>
41
42/*
43 * A table a list of names and their modes.
44 */
45
46typedef struct rtems_rootfs_dir_table
47{
48  const char *name;
49  int        mode;
50} rtems_rootfs_dir_table;
51
52/*
53 * Table of directorys to make.
54 */
55
56static const rtems_rootfs_dir_table default_directories[] =
57{
58  { "/bin",     S_IFDIR | S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH },
59  { "/etc",     S_IFDIR | S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH },
60  { "/dev",     S_IFDIR | S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH },
61  { "/usr/bin", S_IFDIR | S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH }
62};
63
64#define MKFILE_MODE (S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH)
65#define MKDIR_MODE  (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
66
67/*
68 * Build a path. Taken from the BSD `mkdir' command.
69 */
70
71int
72rtems_rootfs_mkdir (const char *path_orig, mode_t omode)
73{
74  struct stat sb;
75  mode_t      numask, oumask;
76  int         first, last, retval;
77  char        path[128];
78  char        *p = path;
79
80  if (strlen (path_orig) >= sizeof path)
81  {
82    printf ("root fs: mkdir path too long `%s'\n", path);
83    return -1;
84  }
85   
86  strcpy (path, path_orig);
87  oumask = 0;
88  retval = 0;
89  if (p[0] == '/')    /* Skip leading '/'. */
90    ++p;
91  for (first = 1, last = 0; !last ; ++p)
92  {
93    if (p[0] == '\0')
94      last = 1;
95    else if (p[0] != '/')
96      continue;
97    *p = '\0';
98    if (p[1] == '\0')
99      last = 1;
100    if (first)
101    {
102      /*
103       * POSIX 1003.2:
104       * For each dir operand that does not name an existing
105       * directory, effects equivalent to those cased by the
106       * following command shall occcur:
107       *
108       * mkdir -p -m $(umask -S),u+wx $(dirname dir) &&
109       *    mkdir [-m mode] dir
110       *
111       * We change the user's umask and then restore it,
112       * instead of doing chmod's.
113       */
114      oumask = umask(0);
115      numask = oumask & ~(S_IWUSR | S_IXUSR);
116      umask(numask);
117      first = 0;
118    }
119    if (last)
120      umask(oumask);
121    if (stat(path, &sb))
122    {
123      if (errno != ENOENT)
124      {
125        printf ("root fs: error stat'ing path `%s', %s\n",
126                path, strerror (errno));
127        retval = 1;
128        break;
129      }
130      if (mkdir(path, last ? omode : S_IRWXU | S_IRWXG | S_IRWXO) < 0)
131      {
132        printf ("root fs: error building path `%s', %s\n",
133                path, strerror (errno));
134        retval = 1;
135        break;
136      }
137    }
138    else if ((sb.st_mode & S_IFMT) != S_IFDIR)
139    {
140      if (last)
141        errno = EEXIST;
142      else
143        errno = ENOTDIR;
144      printf ("root fs: path `%s' contains a file, %s\n",
145              path, strerror (errno));
146      retval = 1;
147      break;
148    }
149    if (!last)
150      *p = '/';
151  }
152  if (!first && !last)
153    umask(oumask);
154  return retval;
155}
156
157/*
158 * Create enough files to support the networking stack.
159 * Points to a table of strings.
160 */
161
162int
163rtems_rootfs_file_append (const char *file,
164                          mode_t     omode,
165                          const int  line_cnt,
166                          const char **lines)
167{
168  struct stat sb;
169  int         fd;
170  int         i;
171
172  /*
173   * See is a file exists. If it does not, create the
174   * file and the path to the file.
175   */
176
177  fd = -1;
178 
179  if (stat(file, &sb))
180  {
181    if (errno == ENOENT)
182    {
183      /*
184       * Get the path to the file if one exists and create the
185       * path. If it exists nothing happens.
186       */
187
188      int i = strlen (file);
189
190      while (i)
191      {
192        if (file[i] == '/')
193        {
194          char path[128];
195
196          if (i >= sizeof path)
197          {
198            printf ("root fs, path too long `%s'\n", file);
199            return -1;
200          }
201
202          strncpy (path, file, i);
203          path[i] = '\0';
204         
205          if (rtems_rootfs_mkdir (path, MKDIR_MODE))
206            return -1;
207          break;
208        }
209        i--;
210      }
211     
212      if ((fd = open (file, O_CREAT | O_APPEND | O_WRONLY, omode)) < 0)
213      {
214        printf ("root fs, cannot create file `%s' : %s\n",
215                file, strerror (errno));
216        return -1;
217      }
218    }
219  }
220
221  if (fd < 0)
222  {
223    if ((fd = open (file, O_APPEND | O_WRONLY)) < 0)
224    {
225      printf ("root fs, cannot open file `%s' : %s\n",
226              file, strerror (errno));
227      return -1;
228    }
229  }
230 
231  for (i = 0; i < line_cnt; i++)
232  {
233    int len = strlen (lines[i]);
234
235    if (len)
236    {
237      if (write (fd, lines[i], strlen (lines[i])) < 0)
238      {
239        close (fd);
240        printf ("root fs, cannot write to `%s' : %s\n",
241                file, strerror (errno));
242        return -1;
243      }
244    }
245  }
246 
247  return close (fd);
248}
249
250/*
251 * Write hosts record.
252 */
253
254int
255rtems_rootfs_append_host_rec (unsigned long cip,
256                              const char    *cname,
257                              const char    *dname)
258{
259  char           buf[128];
260  char           *bufp = buf;
261  const char     *bufl[1];
262  struct in_addr ip;
263
264  ip.s_addr = cip;
265 
266  if (cname && strlen (cname))
267  {
268    snprintf (bufp, sizeof (buf), "%s\t\t%s", inet_ntoa (ip), cname);
269    bufp += strlen (buf);
270
271    if (dname && strlen (dname))
272    {
273      snprintf (bufp, sizeof (buf), "\t\t%s.%s", cname, dname);
274      bufp += strlen (buf);
275    }
276   
277    strcat (buf, "\n");
278 
279    bufl[0] = buf;
280   
281    if (rtems_rootfs_file_append ("/etc/hosts", MKFILE_MODE, 1, bufl) < 0)
282      return -1;
283  }
284  else
285  {
286    printf ("rootfs hosts rec append, no cname supplied\n");
287    return -1;
288  }
289
290  return 0;
291}
292
293/*
294 * Create a root file system.
295 */
296
297int
298rtems_create_root_fs ()
299{
300  const char *lines[1];
301  int        i;
302 
303  /*
304   * Create the directories.
305   */
306
307  for (i = 0;
308       i < (sizeof (default_directories) / sizeof (rtems_rootfs_dir_table));
309       i++)
310    if (rtems_rootfs_mkdir (default_directories[i].name,
311                            default_directories[i].mode))
312      return -1;
313
314  /*
315   * /etc/passwd, /etc/group
316   * Maybe needed by some tools.
317   */
318
319  lines[0] = "root::0:0:root:/root:/bin/sh\n";
320 
321  if (rtems_rootfs_file_append ("/etc/passwd", MKFILE_MODE, 1, lines))
322    return -1;
323 
324  lines[0] = "root::0:root\n";
325 
326  if (rtems_rootfs_file_append ("/etc/group", MKFILE_MODE, 1, lines))
327    return -1;
328
329  /*
330   * The TCP/IP stack likes this one. If DNS does not work
331   * use the host file.
332   */
333 
334  lines[0] = "hosts,bind\n";
335 
336  if (rtems_rootfs_file_append ("/etc/host.conf", MKFILE_MODE, 1, lines))
337    return -1;
338 
339  /*
340   * Create a `/etc/hosts' file.
341   */
342
343  if (rtems_rootfs_append_host_rec (0x7f000001, "localhost", "localdomain"))
344    return -1;
345 
346  return 0;
347}
348
Note: See TracBrowser for help on using the repository browser.