|
|
@@ -1,152 +0,0 @@ |
|
|
|
#include <stdio.h> |
|
|
|
#include <stdlib.h> |
|
|
|
#include <unistd.h> |
|
|
|
#include <dirent.h> |
|
|
|
#include <string.h> |
|
|
|
#include <fnmatch.h> |
|
|
|
#include <libgen.h> |
|
|
|
#include <sys/stat.h> |
|
|
|
|
|
|
|
#include "cfs.h" |
|
|
|
|
|
|
|
#define PUTC(c) putc(c, spitstream) |
|
|
|
|
|
|
|
static FILE *spitstream = NULL; |
|
|
|
|
|
|
|
void set_spit_stream(FILE *stream) |
|
|
|
{ |
|
|
|
spitstream = stream; |
|
|
|
} |
|
|
|
|
|
|
|
int is_regular_file(char *path) |
|
|
|
{ |
|
|
|
struct stat path_stat; |
|
|
|
stat(path, &path_stat); |
|
|
|
return S_ISREG(path_stat.st_mode); |
|
|
|
} |
|
|
|
|
|
|
|
void spitempty() |
|
|
|
{ |
|
|
|
if (spitstream == NULL) spitstream = stdout; |
|
|
|
PUTC('C'); |
|
|
|
PUTC('F'); |
|
|
|
PUTC('S'); |
|
|
|
for (int i=0; i<0x20-3; i++) { |
|
|
|
PUTC(0); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
int spitblock(char *fullpath, char *fn) |
|
|
|
{ |
|
|
|
if (spitstream == NULL) spitstream = stdout; |
|
|
|
FILE *fp = fopen(fullpath, "r"); |
|
|
|
fseek(fp, 0, SEEK_END); |
|
|
|
long fsize = ftell(fp); |
|
|
|
if (fsize > MAX_FILE_SIZE) { |
|
|
|
fclose(fp); |
|
|
|
fprintf(stderr, "File too big: %s %ld\n", fullpath, fsize); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
/* Compute block count. |
|
|
|
* We always have at least one, which contains 0x100 bytes - 0x20, which is |
|
|
|
* metadata. The rest of the blocks have a steady 0x100. |
|
|
|
*/ |
|
|
|
unsigned char blockcount = 1; |
|
|
|
int fsize2 = fsize - (BLKSIZE - HEADERSIZE); |
|
|
|
if (fsize2 > 0) { |
|
|
|
blockcount += (fsize2 / BLKSIZE); |
|
|
|
} |
|
|
|
if (blockcount * BLKSIZE < fsize + HEADERSIZE) { |
|
|
|
blockcount++; |
|
|
|
} |
|
|
|
PUTC('C'); |
|
|
|
PUTC('F'); |
|
|
|
PUTC('S'); |
|
|
|
PUTC(blockcount); |
|
|
|
// file size is little endian |
|
|
|
PUTC(fsize & 0xff); |
|
|
|
PUTC((fsize >> 8) & 0xff); |
|
|
|
int fnlen = strlen(fn); |
|
|
|
for (int i=0; i<MAX_FN_LEN; i++) { |
|
|
|
if (i < fnlen) { |
|
|
|
PUTC(fn[i]); |
|
|
|
} else { |
|
|
|
PUTC(0); |
|
|
|
} |
|
|
|
} |
|
|
|
// And the last FN char which is always null |
|
|
|
PUTC(0); |
|
|
|
char buf[MAX_FILE_SIZE] = {0}; |
|
|
|
rewind(fp); |
|
|
|
fread(buf, fsize, 1, fp); |
|
|
|
fclose(fp); |
|
|
|
fwrite(buf, (blockcount * BLKSIZE) - HEADERSIZE, 1, spitstream); |
|
|
|
fflush(spitstream); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|
|
|
|
int spitdir(char *path, char *prefix, char **patterns) |
|
|
|
{ |
|
|
|
DIR *dp; |
|
|
|
struct dirent *ep; |
|
|
|
|
|
|
|
int prefixlen = strlen(prefix); |
|
|
|
dp = opendir(path); |
|
|
|
if (dp == NULL) { |
|
|
|
fprintf(stderr, "Couldn't open directory.\n"); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
while ((ep = readdir(dp))) { |
|
|
|
if ((strcmp(ep->d_name, ".") == 0) || strcmp(ep->d_name, "..") == 0) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
if (ep->d_type != DT_DIR && ep->d_type != DT_REG) { |
|
|
|
fprintf(stderr, "Only regular file or directories are supported\n"); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
int slen = strlen(ep->d_name); |
|
|
|
if (prefixlen + slen> MAX_FN_LEN) { |
|
|
|
fprintf(stderr, "Filename too long: %s/%s\n", prefix, ep->d_name); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
char fullpath[0x1000]; |
|
|
|
strcpy(fullpath, path); |
|
|
|
strcat(fullpath, "/"); |
|
|
|
strcat(fullpath, ep->d_name); |
|
|
|
char newprefix[MAX_FN_LEN]; |
|
|
|
strcpy(newprefix, prefix); |
|
|
|
if (prefixlen > 0) { |
|
|
|
strcat(newprefix, "/"); |
|
|
|
} |
|
|
|
strcat(newprefix, ep->d_name); |
|
|
|
if (ep->d_type == DT_DIR) { |
|
|
|
int r = spitdir(fullpath, newprefix, patterns); |
|
|
|
if (r != 0) { |
|
|
|
return r; |
|
|
|
} |
|
|
|
} else { |
|
|
|
char **p = patterns; |
|
|
|
// if we have no pattern, we match all |
|
|
|
if (p && *p) { |
|
|
|
int matches = 0; |
|
|
|
while (*p) { |
|
|
|
if (fnmatch(*p, ep->d_name, 0) == 0) { |
|
|
|
matches = 1; |
|
|
|
break; |
|
|
|
} |
|
|
|
p++; |
|
|
|
} |
|
|
|
if (!matches) { |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
int r = spitblock(fullpath, newprefix); |
|
|
|
if (r != 0) { |
|
|
|
return r; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
closedir(dp); |
|
|
|
return 0; |
|
|
|
} |