diff options
Diffstat (limited to 'mkmat.c')
| -rw-r--r-- | mkmat.c | 136 |
1 files changed, 136 insertions, 0 deletions
@@ -0,0 +1,136 @@ +#define _GNU_SOURCE + +#include <errno.h> +#include <fcntl.h> +#include <libgen.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/mman.h> + +#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); +} |
