source: bootcd/isolinux/syslinux-6.03/com32/lib/syslinux/initramfs_file.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 5.0 KB
Line 
1/* ----------------------------------------------------------------------- *
2 *
3 *   Copyright 2007-2008 H. Peter Anvin - All Rights Reserved
4 *
5 *   Permission is hereby granted, free of charge, to any person
6 *   obtaining a copy of this software and associated documentation
7 *   files (the "Software"), to deal in the Software without
8 *   restriction, including without limitation the rights to use,
9 *   copy, modify, merge, publish, distribute, sublicense, and/or
10 *   sell copies of the Software, and to permit persons to whom
11 *   the Software is furnished to do so, subject to the following
12 *   conditions:
13 *
14 *   The above copyright notice and this permission notice shall
15 *   be included in all copies or substantial portions of the Software.
16 *
17 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 *   OTHER DEALINGS IN THE SOFTWARE.
25 *
26 * ----------------------------------------------------------------------- */
27
28/*
29 * initramfs_file.c
30 *
31 * Utility functions to add arbitrary files including cpio header
32 */
33
34#include <stdlib.h>
35#include <stdio.h>
36#include <string.h>
37#include <sys/stat.h>
38#include <syslinux/linux.h>
39
40#define CPIO_MAGIC "070701"
41struct cpio_header {
42    char c_magic[6];            /* 070701 */
43    char c_ino[8];              /* Inode number */
44    char c_mode[8];             /* File mode and permissions */
45    char c_uid[8];              /* uid */
46    char c_gid[8];              /* gid */
47    char c_nlink[8];            /* Number of links */
48    char c_mtime[8];            /* Modification time */
49    char c_filesize[8];         /* Size of data field */
50    char c_maj[8];              /* File device major number */
51    char c_min[8];              /* File device minor number */
52    char c_rmaj[8];             /* Device node reference major number */
53    char c_rmin[8];             /* Device node reference minor number */
54    char c_namesize[8];         /* Length of filename including final \0 */
55    char c_chksum[8];           /* Checksum if c_magic ends in 2 */
56};
57
58static uint32_t next_ino = 1;
59
60/* Create cpio headers for the directory entries leading up to a file.
61   Returns the number of bytes; doesn't touch the buffer if too small. */
62static size_t initramfs_mkdirs(const char *filename, void *buffer,
63                               size_t buflen)
64{
65    const char *p = filename;
66    char *bp = buffer;
67    int len;
68    size_t bytes = 0, hdr_sz;
69    int pad;
70
71    while ((p = strchr(p, '/'))) {
72        if (p != filename && p[-1] != '/') {
73            len = p - filename;
74            bytes += ((sizeof(struct cpio_header) + len + 1) + 3) & ~3;
75        }
76        p++;
77    }
78
79    if (buflen >= bytes) {
80        p = filename;
81        while ((p = strchr(p, '/'))) {
82            if (p != filename && p[-1] != '/') {
83                len = p - filename;
84                hdr_sz = ((sizeof(struct cpio_header) + len + 1) + 3) & ~3;
85                bp += sprintf(bp, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x"
86                              "%08x%08x%08x%08x", next_ino++, S_IFDIR | 0755,
87                              0, 0, 1, 0, 0, 0, 1, 0, 1, len + 1, 0);
88                memcpy(bp, filename, len);
89                bp += len;
90                pad = hdr_sz - (sizeof(struct cpio_header) + len);
91                memset(bp, 0, pad);
92                bp += pad;
93            }
94            p++;
95        }
96    }
97
98    return bytes;
99}
100
101/*
102 * Create a file header (with optional parent directory entries)
103 * and add it to an initramfs chain
104 */
105int initramfs_mknod(struct initramfs *ihead, const char *filename,
106                    int do_mkdir,
107                    uint16_t mode, size_t len, uint32_t major, uint32_t minor)
108{
109    size_t bytes, hdr_sz;
110    int namelen = strlen(filename);
111    int pad;
112    char *buffer, *bp;
113
114    if (do_mkdir)
115        bytes = initramfs_mkdirs(filename, NULL, 0);
116    else
117        bytes = 0;
118
119    hdr_sz = ((sizeof(struct cpio_header) + namelen + 1) + 3) & ~3;
120    bytes += hdr_sz;
121
122    bp = buffer = malloc(bytes);
123    if (!buffer)
124        return -1;
125
126    if (do_mkdir)
127        bp += initramfs_mkdirs(filename, bp, bytes);
128
129    bp += sprintf(bp, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x"
130                  "%08x%08x%08x%08x", next_ino++, mode,
131                  0, 0, 1, 0, len, 0, 1, major, minor, namelen + 1, 0);
132    memcpy(bp, filename, namelen);
133    bp += namelen;
134    pad = hdr_sz - (sizeof(struct cpio_header) + namelen);
135    memset(bp, 0, pad);
136
137    if (initramfs_add_data(ihead, buffer, bytes, bytes, 4)) {
138        free(buffer);
139        return -1;
140    }
141
142    return 0;
143}
144
145/*
146 * Add a file given data in memory to an initramfs chain.  This
147 * can be used to create nonfiles like symlinks by specifying an
148 * appropriate mode.
149 */
150int initramfs_add_file(struct initramfs *ihead, const void *data,
151                       size_t data_len, size_t len,
152                       const char *filename, int do_mkdir, uint32_t mode)
153{
154    if (initramfs_mknod(ihead, filename, do_mkdir,
155                        (mode & S_IFMT) ? mode : mode | S_IFREG, len, 0, 1))
156        return -1;
157
158    return initramfs_add_data(ihead, data, data_len, len, 4);
159}
160
161int initramfs_add_trailer(struct initramfs *ihead)
162{
163    return initramfs_mknod(ihead, "TRAILER!!!", 0, 0, 0, 0, 0);
164}
Note: See TracBrowser for help on using the repository browser.