Rework immutability and overlays
This commit is contained in:
parent
fddf7f86ae
commit
5e65e6c06e
13 changed files with 1141 additions and 70 deletions
98
overlayfs-tools/sh.c
Executable file
98
overlayfs-tools/sh.c
Executable file
|
@ -0,0 +1,98 @@
|
|||
#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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue