summaryrefslogtreecommitdiff
path: root/com32/lib/syslinux/initramfs_file.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2007-03-15 16:57:43 -0700
committerH. Peter Anvin <hpa@zytor.com>2007-03-15 16:57:43 -0700
commitc5e9d7a496936b9ea553be6fef4dff74596bbf11 (patch)
tree2157f08931983c62850f657472b0b86d4ed39e7e /com32/lib/syslinux/initramfs_file.c
parent77481cdf403e4170785fada5a44a0efcd2a357e4 (diff)
downloadsyslinux-c5e9d7a496936b9ea553be6fef4dff74596bbf11.tar.gz
Library functions for manipulating initramfs
Library support for constructing initramfs. This version is *not* complete, as it doesn't take into account alignment requirements properly.
Diffstat (limited to 'com32/lib/syslinux/initramfs_file.c')
-rw-r--r--com32/lib/syslinux/initramfs_file.c154
1 files changed, 154 insertions, 0 deletions
diff --git a/com32/lib/syslinux/initramfs_file.c b/com32/lib/syslinux/initramfs_file.c
new file mode 100644
index 00000000..75b3f29f
--- /dev/null
+++ b/com32/lib/syslinux/initramfs_file.c
@@ -0,0 +1,154 @@
+/* ----------------------------------------------------------------------- *
+ *
+ * Copyright 2007 H. Peter Anvin - All Rights Reserved
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom
+ * the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall
+ * be included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * ----------------------------------------------------------------------- */
+
+/*
+ * initramfs_file.c
+ *
+ * Utility functions to add arbitrary files including cpio header
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <syslinux/linux.h>
+
+#define CPIO_MAGIC "070701"
+struct cpio_header {
+ char c_magic[6]; /* 070701 */
+ char c_ino[8]; /* Inode number */
+ char c_mode[8]; /* File mode and permissions */
+ char c_uid[8]; /* uid */
+ char c_gid[8]; /* gid */
+ char c_nlink[8]; /* Number of links */
+ char c_mtime[8]; /* Modification time */
+ char c_filesize[8]; /* Size of data field */
+ char c_maj[8]; /* File device major number */
+ char c_min[8]; /* File device minor number */
+ char c_rmaj[8]; /* Device node reference major number */
+ char c_rmin[8]; /* Device node reference minor number */
+ char c_namesize[8]; /* Length of filename including final \0 */
+ char c_chksum[8]; /* Checksum if c_magic ends in 2 */
+};
+
+static uint32_t next_ino = 1;
+
+/* Create cpio headers for the directory entries leading up to a file.
+ Returns the number of bytes; doesn't touch the buffer if too small. */
+static size_t initramfs_mkdirs(const char *filename, void *buffer,
+ size_t buflen)
+{
+ const char *p = filename;
+ char *bp = buffer;
+ int len;
+ size_t bytes = 0;
+ int pad;
+
+ while ((p = strchr(p, '/'))) {
+ if (p != filename && p[-1] != '/') {
+ len = p-filename;
+ bytes += ((sizeof(struct cpio_header)+len+1)+3) & ~3;
+ }
+ p++;
+ }
+
+ if (buflen >= bytes) {
+ p = filename;
+ while ((p = strchr(p, '/'))) {
+ if (p != filename && p[-1] != '/') {
+ len = p-filename;
+ bp += sprintf(bp, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x"
+ "%08x%08x%08x%08x", next_ino++, S_IFDIR|0755,
+ 0, 0, 1, 0, 0, 0, 1, 0, 1, len+1, 0);
+ memcpy(bp, filename, len);
+ bp += len;
+ pad = (-(sizeof(struct cpio_header)+len) & 3) + 1;
+ memset(bp, 0, pad);
+ bp += pad;
+ }
+ }
+ }
+
+ return bytes;
+}
+
+int initramfs_mknod(struct initramfs *ihead, const char *filename,
+ int do_mkdir,
+ uint16_t mode, size_t len,
+ uint32_t major, uint32_t minor)
+{
+ size_t bytes;
+ int namelen = strlen(filename);
+ int pad;
+ char *buffer, *bp;
+
+ if (do_mkdir)
+ bytes = initramfs_mkdirs(filename, NULL, 0);
+ else
+ bytes = 0;
+
+ bytes += ((sizeof(struct cpio_header)+namelen+1)+3) & ~3;
+
+ bp = buffer = malloc(bytes);
+ if (!buffer)
+ return -1;
+
+ if (do_mkdir)
+ bp += initramfs_mkdirs(filename, bp, bytes);
+
+ bp += sprintf(bp, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x"
+ "%08x%08x%08x%08x", next_ino++, mode,
+ 0, 0, 1, 0, len, 0, 1, major, minor, len+1, 0);
+ memcpy(bp, filename, namelen);
+ bp += len;
+ pad = (-(sizeof(struct cpio_header)+namelen) & 3) + 1;
+ memset(bp, 0, pad);
+
+ if (initramfs_add_data(ihead, buffer, bytes, bytes)) {
+ free(buffer);
+ return -1;
+ }
+
+ return 0;
+}
+
+int initramfs_add_file(struct initramfs *ihead, const void *data,
+ size_t data_len, size_t len,
+ const char *filename, int do_mkdir, uint32_t mode)
+{
+ if (initramfs_mknod(ihead, filename, do_mkdir,
+ (mode & S_IFMT) ? mode : mode|S_IFREG,
+ len, 0, 1))
+ return -1;
+
+ return initramfs_add_data(ihead, data, data_len, len);
+}
+
+int initramfs_add_trailer(struct initramfs *ihead)
+{
+ return initramfs_mknod(ihead, "TRAILER!!!", 0, 0, 0, 0, 0);
+}