#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include "arg.h" char *argv0; int execveat(int dirfd, const char *path, char *const argv[], char *const envp[], int flags); void die(const char *fmt, ...) { va_list ap; int saved_errno; saved_errno = errno; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); if (fmt[0] && fmt[strlen(fmt)-1] == ':') fprintf(stderr, " %s", strerror(saved_errno)); fputc('\n', stderr); exit(1); } #define usage() die("Usage: %s [filename]", argv0) int main(int argc, char **argv) { ARGBEGIN { default: usage(); } ARGEND if(argc < 1) usage(); int cpwd = open(".", O_PATH | O_CLOEXEC); int file = open(*argv, 0); if(file < 0) die("open file:"); char buf[1 << 8]; size_t linksize = readlink("/proc/self/exe", buf, 1 << 8); if(linksize < 0) die("readlink:"); buf[linksize] = '\0'; char *dname = dirname(buf); chdir(dname); int mkcpio = open("gen_init_cpio", O_CLOEXEC); if(mkcpio < 0) die("open gen_init_cpio:"); fchdir(cpwd); char *argv0_dirname = strdup(*argv); chdir(dirname(argv0_dirname)); free(argv0_dirname); int cpiopipe[2]; if(pipe(cpiopipe) < 0) die("pipe:"); int materialfd = memfd_create("material.mtl", 0); if(materialfd < 0) die("memfd_create:"); int stdout_kept = dup(STDOUT_FILENO); dup2(cpiopipe[0], STDIN_FILENO); dup2(cpiopipe[1], STDOUT_FILENO); //dup2(STDOUT_FILENO, materialpipe[1]); if(cpiopipe[0] != STDIN_FILENO) close(cpiopipe[0]); if(cpiopipe[1] != STDOUT_FILENO) close(cpiopipe[1]); /* all printf go to gen_init_cpio now */ printf("file material.mtl /proc/self/fd/%d 0644 0 0\n", materialfd); size_t num_read = 1; while(num_read > 0) { buf[0] = '\0'; num_read = read(file, buf, (1 << 8) - 2); lseek(file, -num_read, SEEK_CUR); buf[num_read] = '\0'; *strchrnul(buf, '\n') = '\0'; lseek(file, strchrnul(buf, '\n') - buf + 1, SEEK_CUR); if(strncmp(buf, "map_", 4) == 0 || strncmp(buf, "disp ", 5) == 0 || strncmp(buf, "bump ", 5) == 0) { char *name = *argv; #define CASE(val) strncmp(buf, val, strlen(val)) == 0 if(CASE("map_Ka ")) name = "ambient"; else if(CASE("map_Kd ")) name = "diffuse"; else if(CASE("map_Ks ")) name = "specular"; else if(CASE("map_Ns ")) name = "specular_highlight"; else if(CASE("map_bump ") || CASE("bump")) name = "bump"; else if(CASE("disp ")) name = "displacement"; else if(CASE("map_d ")) name = "alpha"; *strchrnul(buf, ' ') = '\0'; dprintf(materialfd, "%s %s\n", buf, name); printf("file %s %s 0644 0 0\n", name, strchrnul(buf, ' ') + 1); } else { dprintf(materialfd, "%s\n", buf); } } fflush(stdout); dup2(stdout_kept, STDOUT_FILENO); if(stdout_kept != STDOUT_FILENO) close(stdout_kept); execveat(mkcpio, "", (char*[]){"gen_init_cpio", "-", NULL}, NULL, AT_EMPTY_PATH); }