diff options
Diffstat (limited to 'scripts/test-shell.c')
-rw-r--r-- | scripts/test-shell.c | 144 |
1 files changed, 144 insertions, 0 deletions
diff --git a/scripts/test-shell.c b/scripts/test-shell.c new file mode 100644 index 00000000..7975c188 --- /dev/null +++ b/scripts/test-shell.c @@ -0,0 +1,144 @@ +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <getopt.h> + +#include <stdint.h> +#include <ftw.h> +#include <errno.h> + +char *readlinka(char const *path){ + size_t buflen = BUFSIZ; + char *buf = malloc(buflen); + ssize_t read; + while ((read = readlink(path, buf, buflen - 1)) >= buflen - 1) { + char *newbuf = realloc(buf, buflen * 2); + if (newbuf == NULL) { + goto failure; + } + buf = newbuf; + buflen = buflen * 2; + } + buf[read] = '\0'; + return buf; +failure: + free(buf); + return NULL; +} + +int copy_file_paths(char const *source_file, char const *target_file) { + int source_fd; + int target_fd; + int ret = -1; + struct stat st; + if ((source_fd = open(source_file, O_RDONLY)) == -1) { + return ret; + } + if (fstat(source_fd, &st) == -1) { + perror("stat"); + ret = -2; + goto cleanup_in; + } + if ((target_fd = open(target_file, O_WRONLY|O_CREAT, st.st_mode)) == -1) { + ret = -3; + goto cleanup_in; + } + ssize_t read; + while ((read = sendfile(target_fd, source_fd, NULL, BUFSIZ)) > 0); + if (read < 0) { + perror("sendfile"); + ret = -4; + } + ret = 0; +cleanup_all: + close(target_fd); +cleanup_in: + close(source_fd); + return ret; +} + +int copy_entry(const char *fpath, const struct stat *sb, int typeflag, + struct FTW *ftwbuf) { + int ret = 0; + char *target_path = NULL; + if (asprintf(&target_path, "%s/%s", getenv("DESTDIR"), fpath) == -1) { + return -1; + } + switch (typeflag) { + case FTW_F: + /* Copy file */ + if ((ret = copy_file_paths(fpath, target_path)) < 0) { + perror("Copy file"); + ret = -1; + } + break; + case FTW_D: + case FTW_DNR: + /* Copy directory */ + if (mkdir(target_path, sb->st_mode)) { + if (errno != EEXIST) { + perror("mkdir"); + ret = -1; + } + } + break; + case FTW_NS: + case FTW_SL: + case FTW_SLN: { + /* Create symlink */ + char *link_target = readlinka(fpath); + if (link_target == NULL) { + perror("readlink"); + ret = -1; + } + if (symlink(link_target, target_path) == -1) { + perror("symlink"); + ret = -1; + } + break; + } + } +cleanup: + free(target_path); + return ret; +} + +int main(int argc, char *argv[]) { + int ret = 1; + if (argc != 3 || strcmp(argv[1], "-c") != 0) { + fprintf(stderr, "Usage: %s -c COMMAND\n", argv[0]); + return 1; + } + size_t cmdlen = strlen(argv[2]); + FILE *cmdstream = fmemopen(argv[2], cmdlen, "r"); + { + ssize_t read; + size_t len = 0; + char *line = NULL; + + ret = 0; + while ((read = getline(&line, &len, cmdstream)) != -1) { + if (line[read - 1] == '\n') line[read - 1] = '\0'; + if (strcmp(line, "copy files") == 0) { + /* Recursively copy contents of current dir to DESTDIR */ + if (nftw(".", copy_entry, 20, FTW_PHYS)) { + ret = 1; + break; + } + } else if (strcmp(line, "false") == 0 || + strstr(line, "false ") == line) { + ret = 1; + break; + } else { + ret = 127; + break; + } + } + free(line); + } + return ret; +} |