#define _GNU_SOURCE #include #include #include #include #include #include #include "sh.h" char * vars[NUM_VARS]; const char * var_names[NUM_VARS] = { "LOWERDIR", "UPPERDIR", "MOUNTDIR", "LOWERNEW", "UPPERNEW", }; int quote(const char *filename, FILE *output); FILE* create_shell_script(char *tmp_path_buffer) { int tmp_file = mkstemps(tmp_path_buffer, 3); // the 3 is for suffix length (".sh") if (tmp_file < 0) { return NULL; } fchmod(tmp_file, S_IRWXU); // chmod to 0700 FILE* f = fdopen(tmp_file, "w"); if (f == NULL) { return NULL; } fprintf(f, "#!/usr/bin/env bash\n"); fprintf(f, "set -x\n"); time_t rawtime; time (&rawtime); fprintf(f, "# This shell script is generated by overlayfs-tools on %s\n", ctime (&rawtime)); for (int i=0; i < NUM_VARS; i++) { if (vars[i]) { fprintf(f, "%s=", var_names[i]); if (quote(vars[i], f) < 0) { return NULL; } if (fputc('\n', f) == EOF) { return NULL; } } } // Non-empty *NEW vars make a backup copy and override *DIR vars if (vars[LOWERNEW]) { fprintf(f, "rm -rf \"$LOWERNEW\"\n"); fprintf(f, "cp -a \"$LOWERDIR\" \"$LOWERNEW\"\n"); fprintf(f, "LOWERDIR="); if (quote(vars[LOWERNEW], f) < 0) { return NULL; } if (fputc('\n', f) == EOF) { return NULL; } } if (vars[UPPERNEW]) { fprintf(f, "rm -rf \"$UPPERNEW\"\n"); fprintf(f, "cp -a \"$UPPERDIR\" \"$UPPERNEW\"\n"); fprintf(f, "UPPERDIR="); if (quote(vars[UPPERNEW], f) < 0) { return NULL; } if (fputc('\n', f) == EOF) { return NULL; } } return f; } int quote(const char *filename, FILE *output) { if (fputc('\'', output) == EOF) { return -1; } for (const char *s = filename; *s != '\0'; s++) { if (*s == '\'') { if (fprintf(output, "'\"'\"'") < 0) { return -1; } } else { if (fputc(*s, output) == EOF) { return -1; } } } if (fputc('\'', output) == EOF) { return -1; } return 0; } int substitue(char what, const char *filename, FILE *output) { int i; for (i=0; i < NUM_VARS; i++) if (vars[i] && var_names[i][0] == what) break; if (i == NUM_VARS) { return -1; } // filename prefix must match the var value int prefix = strlen(vars[i]); if (strncmp(filename, vars[i], prefix)) { return -1; } filename += prefix; fprintf(output, "\"$%s\"", var_names[i]); return quote(filename, output); } int command(FILE *output, const char *command_format, ...) { va_list arg; va_start(arg, command_format); for (size_t i = 0; command_format[i] != '\0'; i++) { if (command_format[i] == '%') { const char *s = va_arg(arg, char *); if (substitue(command_format[++i], s, output) < 0) { return -1; } } else { if (fputc(command_format[i], output) == EOF) { return -1; } } } va_end(arg); if (fputc('\n', output) == EOF) { return -1; } return 0; }