Extract parse_cpio_entries() from KFS
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 6 Mar 2018 22:18:00 +0000 (14:18 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Mon, 30 Apr 2018 18:31:44 +0000 (14:31 -0400)
Moves it from KFS to cpio.c, so we can use it in other places.  I
attempted to update it a bit, including size checks.

Signed-off-by: Barret Rhoden <brho@cs.berkeley.edu>
kern/include/cpio.h
kern/lib/Kbuild
kern/lib/cpio.c [new file with mode: 0644]
kern/src/kfs.c

index 556be50..d110b25 100644 (file)
@@ -52,7 +52,8 @@ struct cpio_bin_hdr
        void                    *c_filestart;
 };
 
-void parse_cpio_entries(struct super_block *sb, void *cpio_b);
+void parse_cpio_entries(void *cpio_b, size_t cpio_sz,
+                        int (*cb)(struct cpio_bin_hdr*, void *), void *cb_arg);
 
 /* Helper function: converts src non-null-term string's n bytes from base 16 to
  * a long, using buf as space.  Make sure buf is n + 1. */
index 0b0df9b..a0e33c3 100644 (file)
@@ -1,5 +1,6 @@
 obj-y                                          += address_range.o
 obj-y                                          += circular_buffer.o
+obj-y                                          += cpio.o
 obj-y                                          += rbtree.o
 obj-y                                          += slice.o
 obj-y                                          += sort.o
diff --git a/kern/lib/cpio.c b/kern/lib/cpio.c
new file mode 100644 (file)
index 0000000..eafdafa
--- /dev/null
@@ -0,0 +1,63 @@
+#include <cpio.h>
+#include <kmalloc.h>
+#include <stdio.h>
+#include <string.h>
+
+void parse_cpio_entries(void *cpio_b, size_t cpio_sz,
+                        int (*cb)(struct cpio_bin_hdr*, void *), void *cb_arg)
+{
+       struct cpio_newc_header *c_hdr;
+       char buf[9] = {0};      /* temp space for strol conversions */
+       size_t namesize = 0;
+       int offset = 0;         /* offset in the cpio archive */
+       struct cpio_bin_hdr *c_bhdr = kzmalloc(sizeof(*c_bhdr), MEM_WAIT);
+
+       /* read all files and paths */
+       for (;;) {
+               c_hdr = (struct cpio_newc_header*)(cpio_b + offset);
+               offset += sizeof(*c_hdr);
+               if (offset > cpio_sz) {
+                       printk("CPIO offset %d beyond size %d, aborting.\n", offset,
+                              cpio_sz);
+                       return;
+               }
+               if (strncmp(c_hdr->c_magic, "070701", 6)) {
+                       printk("Invalid magic number in CPIO header, aborting.\n");
+                       return;
+               }
+               c_bhdr->c_filename = (char*)c_hdr + sizeof(*c_hdr);
+               namesize = cpio_strntol(buf, c_hdr->c_namesize, 8);
+               printd("Namesize: %d\n", namesize);
+               if (!strcmp(c_bhdr->c_filename, "TRAILER!!!"))
+                       break;
+               c_bhdr->c_ino = cpio_strntol(buf, c_hdr->c_ino, 8);
+               c_bhdr->c_mode = (int)cpio_strntol(buf, c_hdr->c_mode, 8);
+               c_bhdr->c_uid = cpio_strntol(buf, c_hdr->c_uid, 8);
+               c_bhdr->c_gid = cpio_strntol(buf, c_hdr->c_gid, 8);
+               c_bhdr->c_nlink = (unsigned int)cpio_strntol(buf, c_hdr->c_nlink, 8);
+               c_bhdr->c_mtime = cpio_strntol(buf, c_hdr->c_mtime, 8);
+               c_bhdr->c_filesize = cpio_strntol(buf, c_hdr->c_filesize, 8);
+               c_bhdr->c_dev_maj = cpio_strntol(buf, c_hdr->c_dev_maj, 8);
+               c_bhdr->c_dev_min = cpio_strntol(buf, c_hdr->c_dev_min, 8);
+               c_bhdr->c_rdev_maj = cpio_strntol(buf, c_hdr->c_rdev_maj, 8);
+               c_bhdr->c_rdev_min = cpio_strntol(buf, c_hdr->c_rdev_min, 8);
+               printd("File: %s: %d Bytes\n", c_bhdr->c_filename, c_bhdr->c_filesize);
+               offset += namesize;
+               /* header + name will be padded out to 4-byte alignment */
+               offset = ROUNDUP(offset, 4);
+               c_bhdr->c_filestart = cpio_b + offset;
+               offset += c_bhdr->c_filesize;
+               offset = ROUNDUP(offset, 4);
+               if (offset > cpio_sz) {
+                       printk("CPIO offset %d beyond size %d, aborting.\n", offset,
+                              cpio_sz);
+                       return;
+               }
+               if (cb(c_bhdr, cb_arg)) {
+                       printk("Failed to handle CPIO callback, aborting!\n");
+                       break;
+               }
+               //printk("offset is %d bytes\n", offset);
+       }
+       kfree(c_bhdr);
+}
index 251e9e6..e851e28 100644 (file)
@@ -30,6 +30,8 @@ struct file_operations kfs_f_op_file;
 struct file_operations kfs_f_op_dir;
 struct file_operations kfs_f_op_sym;
 
+static int add_kfs_entry(struct cpio_bin_hdr *c_bhdr, void *cb_arg);
+
 /* TODO: something more better.  Prob something like the vmem cache, for this,
  * pids, etc.  Good enough for now.  This also means we can only have one
  * KFS instance, and we also aren't synchronizing access. */
@@ -93,7 +95,9 @@ struct super_block *kfs_get_sb(struct fs_type *fs, int flags,
        /* 1 is the KFS root ino (inode number) */
        init_sb(sb, vmnt, &kfs_d_op, 1, 0);
        /* Parses the CPIO entries and builds the in-memory KFS tree. */
-       parse_cpio_entries(sb, sb->s_fs_info);
+       parse_cpio_entries(sb->s_fs_info,
+                          (size_t)_binary_obj_kern_initramfs_cpio_size,
+                          add_kfs_entry, sb);
        printk("KFS superblock loaded\n");
        return sb;
 }
@@ -910,62 +914,13 @@ static int __add_kfs_entry(struct dentry *parent, char *path,
  * If a directory does not exist for a file, this will return an error.  Don't
  * use the -depth flag to find when building the CPIO archive, and this won't be
  * a problem.  (Maybe) */
-static int add_kfs_entry(struct super_block *sb, struct cpio_bin_hdr *c_bhdr)
+static int add_kfs_entry(struct cpio_bin_hdr *c_bhdr, void *cb_arg)
 {
+       struct super_block *sb = cb_arg;
        char *path = c_bhdr->c_filename;
+
        /* Root of the FS, already part of KFS */
        if (!strcmp(path, "."))
                return 0;
        return __add_kfs_entry(sb->s_mount->mnt_root, path, c_bhdr);
 }
-
-void parse_cpio_entries(struct super_block *sb, void *cpio_b)
-{
-       struct cpio_newc_header *c_hdr = (struct cpio_newc_header*)cpio_b;
-
-       char buf[9] = {0};      /* temp space for strol conversions */
-       size_t namesize = 0;
-       int offset = 0;         /* offset in the cpio archive */
-       struct cpio_bin_hdr *c_bhdr = kmalloc(sizeof(*c_bhdr), 0);
-       memset(c_bhdr, 0, sizeof(*c_bhdr));
-
-       /* read all files and paths */
-       for (; ; c_hdr = (struct cpio_newc_header*)(cpio_b + offset)) {
-               offset += sizeof(*c_hdr);
-               if (strncmp(c_hdr->c_magic, "070701", 6)) {
-                       printk("Invalid magic number in CPIO header, aborting.\n");
-                       return;
-               }
-               c_bhdr->c_filename = (char*)c_hdr + sizeof(*c_hdr);
-               namesize = cpio_strntol(buf, c_hdr->c_namesize, 8);
-               printd("Namesize: %d\n", namesize);
-               if (!strcmp(c_bhdr->c_filename, "TRAILER!!!"))
-                       break;
-               c_bhdr->c_ino = cpio_strntol(buf, c_hdr->c_ino, 8);
-               c_bhdr->c_mode = (int)cpio_strntol(buf, c_hdr->c_mode, 8);
-               c_bhdr->c_uid = cpio_strntol(buf, c_hdr->c_uid, 8);
-               c_bhdr->c_gid = cpio_strntol(buf, c_hdr->c_gid, 8);
-               c_bhdr->c_nlink = (unsigned int)cpio_strntol(buf, c_hdr->c_nlink, 8);
-               c_bhdr->c_mtime = cpio_strntol(buf, c_hdr->c_mtime, 8);
-               c_bhdr->c_filesize = cpio_strntol(buf, c_hdr->c_filesize, 8);
-               c_bhdr->c_dev_maj = cpio_strntol(buf, c_hdr->c_dev_maj, 8);
-               c_bhdr->c_dev_min = cpio_strntol(buf, c_hdr->c_dev_min, 8);
-               c_bhdr->c_rdev_maj = cpio_strntol(buf, c_hdr->c_rdev_maj, 8);
-               c_bhdr->c_rdev_min = cpio_strntol(buf, c_hdr->c_rdev_min, 8);
-               printd("File: %s: %d Bytes\n", c_bhdr->c_filename, c_bhdr->c_filesize);
-               offset += namesize;
-               /* header + name will be padded out to 4-byte alignment */
-               offset = ROUNDUP(offset, 4);
-               c_bhdr->c_filestart = cpio_b + offset;
-               /* make this a function pointer or something */
-               if (add_kfs_entry(sb, c_bhdr)) {
-                       printk("Failed to add an entry to KFS!\n");
-                       break;
-               }
-               offset += c_bhdr->c_filesize;
-               offset = ROUNDUP(offset, 4);
-               //printk("offset is %d bytes\n", offset);
-               c_hdr = (struct cpio_newc_header*)(cpio_b + offset);
-       }
-       kfree(c_bhdr);
-}