98 lines
3 KiB
C
Executable file
98 lines
3 KiB
C
Executable file
#define _GNU_SOURCE
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include <time.h>
|
|
#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;
|
|
}
|