#include <stdio.h>#include <stdlib.h>#include <string.h>#include <fcntl.h>#include <unistd.h>#include <sys/stat.h>#include <sys/time.h>#include <sys/wait.h>#include <libgen.h>#include <openssl/sha.h> #define nil NULL intmain(int argc, char **argv){ char *path, *e, *origexe, *s, exe[4096], *argv0, *in, *out, *dirout, dhh[SHA256_DIGEST_LENGTH*2+1]; uint8_t tmp[65536], dh[SHA256_DIGEST_LENGTH]; int d, f, i, argout; SHA256_CTX shactx; struct stat st; ssize_t n; pid_t pid; if((dirout = getenv("LLCACHE_DIR")) == nil){ fprintf(stderr, "LLCACHE_DIR not set\n"); goto err; } if((argv0 = basename(argv[0])) == nil){ fprintf(stderr, "argv[0] is not a proper path\n"); goto err; } if((n = readlink("/proc/self/exe", exe, sizeof(exe))) >= (ssize_t)sizeof(exe)){exesmall: fprintf(stderr, "exe buffer too small\n"); goto err; }else if(n < 0){ perror("exe buffer"); goto err; } exe[n] = 0; origexe = realpath(exe, nil); path = strdup(getenv("PATH")); for(s = path; s != nil; s = e ? e + 1 : nil){ if((e = strchr(s, ':')) != nil) *e = 0; if((d = open(s, O_DIRECTORY|O_RDONLY)) < 0) continue; n = readlinkat(d, argv0, exe, sizeof(exe)); if(n >= (ssize_t)sizeof(exe)) goto exesmall; if(n < 0){ if((n = fstatat(d, argv0, &st, 0)) == 0) exe[0] = 0; } close(d); if(n < 0 || strcmp(origexe, exe) == 0) continue; if(snprintf(exe, sizeof(exe), "%s/%s", s, argv0) >= (int)sizeof(exe)) goto exesmall; if((s = realpath(exe, nil)) == nil || strcmp(origexe, s) == 0){ free(s); continue; } break; } if(s == nil){ fprintf(stderr, "%s: not found\n", argv0); goto err; } SHA256_Init(&shactx); SHA256_Update(&shactx, s, strlen(s)+1); in = nil; out = nil; argout = -1; for(i = 1; i < argc; i++){ if(argv[i][0] == '/'){ if(strcmp(argv[i-1], "-o") == 0){ out = argv[i]; argout = i; }else{ in = argv[i]; } }else{ SHA256_Update(&shactx, argv[i], strlen(argv[i])+1); } } if(in == nil || out == nil) goto run; if((f = open(in, O_RDONLY)) < 0){inerr: perror("input"); goto err; } for(;;){ if((n = read(f, tmp, sizeof(tmp))) == 0) break; if(n < 0) goto inerr; SHA256_Update(&shactx, tmp, n); } close(f); SHA256_Final(dh, &shactx); for(i = 0; i < (int)sizeof(dh); i++) sprintf(&dhh[i*2], "%02x", dh[i]); pid = 0;copy: if((d = open(dirout, O_DIRECTORY)) >= 0 && (f = openat(d, dhh, O_RDONLY)) >= 0 && fstat(f, &st) == 0){ close(d); if((d = creat(out, st.st_mode)) < 0){ perror("creat"); goto err; } for(;;){ if((n = read(f, tmp, sizeof(tmp))) == 0) break; if(n < 0) goto inerr; if(write(d, tmp, n) != n){ perror("output"); goto err; } } close(f); close(d); return 0; } if(pid != 0){ fprintf(stderr, "endless loop?\n"); goto err; } run: if((pid = fork()) < 0){ perror("fork"); goto err; }else if(pid == 0){ if(argout > 0){ snprintf((char*)tmp, sizeof(tmp), "%s/%s", dirout, dhh); argv[argout] = (char*)tmp; } execvp(s, argv); perror("exec"); goto err; } if(waitpid(pid, &i, 0) < 0){ perror("waitpid"); goto err; } if(i == 0) goto copy;err: return 1;}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <libgen.h>
#include <openssl/sha.h>
#define nil NULL
int
main(int argc, char **argv)
{
char *path, *e, *origexe, *s, exe[4096], *argv0, *in, *out, *dirout, dhh[SHA256_DIGEST_LENGTH*2+1];
uint8_t tmp[65536], dh[SHA256_DIGEST_LENGTH];
int d, f, i, argout;
SHA256_CTX shactx;
struct stat st;
ssize_t n;
pid_t pid;
if((dirout = getenv("LLCACHE_DIR")) == nil){
fprintf(stderr, "LLCACHE_DIR not set\n");
goto err;
}
if((argv0 = basename(argv[0])) == nil){
fprintf(stderr, "argv[0] is not a proper path\n");
goto err;
}
if((n = readlink("/proc/self/exe", exe, sizeof(exe))) >= (ssize_t)sizeof(exe)){
exesmall:
fprintf(stderr, "exe buffer too small\n");
goto err;
}else if(n < 0){
perror("exe buffer");
goto err;
}
exe[n] = 0;
origexe = realpath(exe, nil);
path = strdup(getenv("PATH"));
for(s = path; s != nil; s = e ? e + 1 : nil){
if((e = strchr(s, ':')) != nil)
*e = 0;
if((d = open(s, O_DIRECTORY|O_RDONLY)) < 0)
continue;
n = readlinkat(d, argv0, exe, sizeof(exe));
if(n >= (ssize_t)sizeof(exe))
goto exesmall;
if(n < 0){
if((n = fstatat(d, argv0, &st, 0)) == 0)
exe[0] = 0;
}
close(d);
if(n < 0 || strcmp(origexe, exe) == 0)
continue;
if(snprintf(exe, sizeof(exe), "%s/%s", s, argv0) >= (int)sizeof(exe))
goto exesmall;
if((s = realpath(exe, nil)) == nil || strcmp(origexe, s) == 0){
free(s);
continue;
}
break;
}
if(s == nil){
fprintf(stderr, "%s: not found\n", argv0);
goto err;
}
SHA256_Init(&shactx);
SHA256_Update(&shactx, s, strlen(s)+1);
in = nil;
out = nil;
argout = -1;
for(i = 1; i < argc; i++){
if(argv[i][0] == '/'){
if(strcmp(argv[i-1], "-o") == 0){
out = argv[i];
argout = i;
}else{
in = argv[i];
}
}else{
SHA256_Update(&shactx, argv[i], strlen(argv[i])+1);
}
}
if(in == nil || out == nil)
goto run;
if((f = open(in, O_RDONLY)) < 0){
inerr:
perror("input");
goto err;
}
for(;;){
if((n = read(f, tmp, sizeof(tmp))) == 0)
break;
if(n < 0)
goto inerr;
SHA256_Update(&shactx, tmp, n);
}
close(f);
SHA256_Final(dh, &shactx);
for(i = 0; i < (int)sizeof(dh); i++)
sprintf(&dhh[i*2], "%02x", dh[i]);
pid = 0;
copy:
if((d = open(dirout, O_DIRECTORY)) >= 0 && (f = openat(d, dhh, O_RDONLY)) >= 0 && fstat(f, &st) == 0){
close(d);
if((d = creat(out, st.st_mode)) < 0){
perror("creat");
goto err;
}
for(;;){
if((n = read(f, tmp, sizeof(tmp))) == 0)
break;
if(n < 0)
goto inerr;
if(write(d, tmp, n) != n){
perror("output");
goto err;
}
}
close(f);
close(d);
return 0;
}
if(pid != 0){
fprintf(stderr, "endless loop?\n");
goto err;
}
run:
if((pid = fork()) < 0){
perror("fork");
goto err;
}else if(pid == 0){
if(argout > 0){
snprintf((char*)tmp, sizeof(tmp), "%s/%s", dirout, dhh);
argv[argout] = (char*)tmp;
}
execvp(s, argv);
perror("exec");
goto err;
}
if(waitpid(pid, &i, 0) < 0){
perror("waitpid");
goto err;
}
if(i == 0)
goto copy;
err:
return 1;
}