summaryrefslogtreecommitdiff
path: root/cpio
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
committerThe Android Open Source Project <initial-contribution@android.com>2008-10-21 07:00:00 -0700
commit4f6e8d7a00cbeda1e70cc15be9c4af1018bdad53 (patch)
tree54fd1b2695a591d2306d41264df67c53077b752c /cpio
Initial Contribution
Diffstat (limited to 'cpio')
-rw-r--r--cpio/Android.mk13
-rw-r--r--cpio/mkbootfs.c220
2 files changed, 233 insertions, 0 deletions
diff --git a/cpio/Android.mk b/cpio/Android.mk
new file mode 100644
index 000000000..f340fd69a
--- /dev/null
+++ b/cpio/Android.mk
@@ -0,0 +1,13 @@
+# Copyright 2005 The Android Open Source Project
+
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ mkbootfs.c
+
+LOCAL_MODULE := mkbootfs
+
+include $(BUILD_HOST_EXECUTABLE)
+
+$(call dist-for-goals,user userdebug droid,$(LOCAL_BUILT_MODULE))
diff --git a/cpio/mkbootfs.c b/cpio/mkbootfs.c
new file mode 100644
index 000000000..9fe625278
--- /dev/null
+++ b/cpio/mkbootfs.c
@@ -0,0 +1,220 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+#include <stdarg.h>
+#include <fcntl.h>
+
+#include <private/android_filesystem_config.h>
+
+/* NOTES
+**
+** - see buffer-format.txt from the linux kernel docs for
+** an explanation of this file format
+** - dotfiles are ignored
+** - directories named 'root' are ignored
+** - device notes, pipes, etc are not supported (error)
+*/
+
+void die(const char *why, ...)
+{
+ va_list ap;
+
+ va_start(ap, why);
+ fprintf(stderr,"error: ");
+ vfprintf(stderr, why, ap);
+ fprintf(stderr,"\n");
+ va_end(ap);
+ exit(1);
+}
+
+static int verbose = 0;
+static int total_size = 0;
+
+static void fix_stat(const char *path, struct stat *s)
+{
+ fs_config(path, S_ISDIR(s->st_mode), &s->st_uid, &s->st_gid, &s->st_mode);
+}
+
+static void _eject(struct stat *s, char *out, int olen, char *data, unsigned datasize)
+{
+ while(total_size & 3) {
+ total_size++;
+ putchar(0);
+ }
+
+ fix_stat(out, s);
+// fprintf(stderr, "_eject %s: mode=0%o\n", out, s->st_mode);
+
+ printf("%06x%08x%08x%08x%08x%08x%08x"
+ "%08x%08x%08x%08x%08x%08x%08x%s%c",
+ 0x070701,
+ (unsigned) s->st_ino,
+ s->st_mode,
+ 0, // s.st_uid,
+ 0, // s.st_gid,
+ 1, // s.st_nlink,
+ (unsigned) s->st_mtime,
+ datasize,
+ 0, // volmajor
+ 0, // volminor
+ 0, // devmajor
+ 0, // devminor,
+ olen + 1,
+ 0,
+ out,
+ 0
+ );
+
+ total_size += 6 + 8*13 + olen + 1;
+
+ if(strlen(out) != olen) die("ACK!");
+
+ while(total_size & 3) {
+ total_size++;
+ putchar(0);
+ }
+
+ if(datasize) {
+ fwrite(data, datasize, 1, stdout);
+ total_size += datasize;
+ }
+}
+
+static void _eject_trailer()
+{
+ struct stat s;
+ memset(&s, 0, sizeof(s));
+ _eject(&s, "TRAILER!!!", 10, 0, 0);
+
+ while(total_size & 0xff) {
+ total_size++;
+ putchar(0);
+ }
+}
+
+static void _archive(char *in, char *out, int ilen, int olen);
+
+static void _archive_dir(char *in, char *out, int ilen, int olen)
+{
+ int t;
+ DIR *d;
+ struct dirent *de;
+
+ if(verbose) {
+ fprintf(stderr,"_archive_dir('%s','%s',%d,%d)\n",
+ in, out, ilen, olen);
+ }
+
+ d = opendir(in);
+ if(d == 0) die("cannot open directory '%s'", in);
+
+ while((de = readdir(d)) != 0){
+ /* xxx: feature? maybe some dotfiles are okay */
+ if(de->d_name[0] == '.') continue;
+
+ /* xxx: hack. use a real exclude list */
+ if(!strcmp(de->d_name, "root")) continue;
+
+ t = strlen(de->d_name);
+ in[ilen] = '/';
+ memcpy(in + ilen + 1, de->d_name, t + 1);
+
+ if(olen > 0) {
+ out[olen] = '/';
+ memcpy(out + olen + 1, de->d_name, t + 1);
+ _archive(in, out, ilen + t + 1, olen + t + 1);
+ } else {
+ memcpy(out, de->d_name, t + 1);
+ _archive(in, out, ilen + t + 1, t);
+ }
+
+ in[ilen] = 0;
+ out[olen] = 0;
+ }
+}
+
+static void _archive(char *in, char *out, int ilen, int olen)
+{
+ struct stat s;
+
+ if(verbose) {
+ fprintf(stderr,"_archive('%s','%s',%d,%d)\n",
+ in, out, ilen, olen);
+ }
+
+ if(lstat(in, &s)) die("could not stat '%s'\n", in);
+
+ if(S_ISREG(s.st_mode)){
+ char *tmp;
+ int fd;
+
+ fd = open(in, O_RDONLY);
+ if(fd < 0) die("cannot open '%s' for read", in);
+
+ tmp = (char*) malloc(s.st_size);
+ if(tmp == 0) die("cannot allocate %d bytes", s.st_size);
+
+ if(read(fd, tmp, s.st_size) != s.st_size) {
+ die("cannot read %d bytes", s.st_size);
+ }
+
+ _eject(&s, out, olen, tmp, s.st_size);
+
+ free(tmp);
+ close(fd);
+ } else if(S_ISDIR(s.st_mode)) {
+ _eject(&s, out, olen, 0, 0);
+ _archive_dir(in, out, ilen, olen);
+ } else if(S_ISLNK(s.st_mode)) {
+ char buf[1024];
+ int size;
+ size = readlink(in, buf, 1024);
+ if(size < 0) die("cannot read symlink '%s'", in);
+ _eject(&s, out, olen, buf, size);
+ } else {
+ die("Unknown '%s' (mode %d)?\n", in, s.st_mode);
+ }
+}
+
+void archive(const char *start, const char *prefix)
+{
+ char in[8192];
+ char out[8192];
+
+ strcpy(in, start);
+ strcpy(out, prefix);
+
+ _archive_dir(in, out, strlen(in), strlen(out));
+}
+
+int main(int argc, char *argv[])
+{
+ argc--;
+ argv++;
+
+ if(argc == 0) die("no directories to process?!");
+
+ while(argc-- > 0){
+ char *x = strchr(*argv, '=');
+ if(x != 0) {
+ *x++ = 0;
+ } else {
+ x = "";
+ }
+
+ archive(*argv, x);
+
+ argv++;
+ }
+
+ _eject_trailer();
+
+ return 0;
+}