|
|
@@ -23,7 +23,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/> |
|
|
|
#include <string.h> |
|
|
|
#include <getopt.h> |
|
|
|
|
|
|
|
#define VERSION "0.2" |
|
|
|
#define VERSION "0.4" |
|
|
|
typedef uint32_t loc_t; |
|
|
|
typedef uint8_t byte; |
|
|
|
#define CD_SECTOR_SIZE 0x800 /* 2048 */ |
|
|
@@ -38,9 +38,9 @@ typedef uint8_t bool; |
|
|
|
#define ALIGN(x,y) (((x) + ((y)-1)) & (~((y)-1))) |
|
|
|
|
|
|
|
static char *isofilename, *targetfilename, *targetdirname, *hostfilename; |
|
|
|
static bool length_override = false; |
|
|
|
static bool ecrase = false; |
|
|
|
|
|
|
|
struct iso_directory_t { |
|
|
|
struct iso_rep_t { |
|
|
|
uint8_t len; |
|
|
|
uint8_t ex_len; |
|
|
|
uint32_t lba; |
|
|
@@ -56,7 +56,7 @@ struct iso_directory_t { |
|
|
|
uint8_t fileid_len; |
|
|
|
char fileid[0]; |
|
|
|
} __attribute__((packed)); |
|
|
|
typedef struct iso_directory_t iso_directory_t; |
|
|
|
typedef struct iso_rep_t iso_rep_t; |
|
|
|
|
|
|
|
int getfilesize(FILE *f) { |
|
|
|
int spos = ftell(f); |
|
|
@@ -65,8 +65,8 @@ int getfilesize(FILE *f) { |
|
|
|
fseek(f, spos, SEEK_SET); |
|
|
|
return len; |
|
|
|
} |
|
|
|
static int verbose_flag; |
|
|
|
static int mode_flag=-2; /* 0=list, 1=put, -1=get */ |
|
|
|
static int Verbose; |
|
|
|
static int Mode=-2; /* 0=list, 1=put, -1=get */ |
|
|
|
|
|
|
|
void CdSetloc(FILE *f, loc_t newpos) { |
|
|
|
fseeko(f, newpos * CD_SECTOR_SIZE, SEEK_SET); |
|
|
@@ -81,10 +81,7 @@ void CdWrite(void *buf, loc_t nsectors, FILE *f) { |
|
|
|
} |
|
|
|
|
|
|
|
bool ispvd(byte *sec) { |
|
|
|
return( |
|
|
|
(sec[0] == 1) && |
|
|
|
(memcmp(sec+1, "CD001", 5) == 0) |
|
|
|
); |
|
|
|
return( (sec[0] == 1) && (memcmp(sec+1, "CD001", 5) == 0)); |
|
|
|
} |
|
|
|
|
|
|
|
bool streq(const char *s1, const char *s2) { |
|
|
@@ -93,84 +90,73 @@ bool streq(const char *s1, const char *s2) { |
|
|
|
|
|
|
|
bool scmplen(const char *s1, const char *s2, int len) { |
|
|
|
for(int i = 0; i < len; i += 1) { |
|
|
|
if(tolower(s1[i]) != tolower(s2[i])) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
if(tolower(s1[i]) != tolower(s2[i])) return false; |
|
|
|
} |
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
|
loc_t CdTell(FILE *isofile) { |
|
|
|
loc_t s = ftell(isofile); |
|
|
|
loc_t CdTell(FILE *fdi) { |
|
|
|
loc_t s = ftell(fdi); |
|
|
|
return (s & (~(0x7FF))) / 0x800; |
|
|
|
} |
|
|
|
|
|
|
|
bool CdFindFileInDir(iso_directory_t *out_dir, FILE* isofile, const char *filename, int filename_len, loc_t *out_secnum, loc_t *out_offset) { |
|
|
|
bool CdFindFileInDir(iso_rep_t *out_dir, FILE* fdi, const char *filename, int filename_len, loc_t *out_secnum, loc_t *out_offset) { |
|
|
|
byte sec[CD_SECTOR_SIZE]; |
|
|
|
iso_directory_t *dir = (iso_directory_t*)(sec); |
|
|
|
iso_rep_t *dir = (iso_rep_t*)(sec); |
|
|
|
int slen = filename_len; |
|
|
|
int dirp = 0; |
|
|
|
|
|
|
|
CdRead(sec, 1, isofile); |
|
|
|
CdRead(sec, 1, fdi); |
|
|
|
|
|
|
|
if (verbose_flag) printf("FFID %s %d\n", filename, slen); |
|
|
|
|
|
|
|
if (Verbose) printf("FFID %s %d\n", filename, slen); |
|
|
|
|
|
|
|
while(dir->len != 0) { |
|
|
|
int dlen = dir->fileid_len; |
|
|
|
if(!(dir->file_flags & 2)) { |
|
|
|
dlen -= 2; |
|
|
|
} |
|
|
|
if ((mode_flag == 0) && ((strcmp(filename,"*")==0)||(strcmp(filename,"/*")==0))) { |
|
|
|
if(!(dir->file_flags & 2)) dlen -= 2; |
|
|
|
if ((Mode == 0)&&((strcmp(filename,"*")==0)||(strcmp(filename,"/*")==0))){ |
|
|
|
if (dlen>0) { |
|
|
|
dir->fileid[dlen] = '\0'; |
|
|
|
if ((dlen==1) && (dir->fileid[0] <= ' ')) { |
|
|
|
if (verbose_flag) printf(" + 0x%x %d\n",(int)dir->fileid[0], dlen); |
|
|
|
if (Verbose) printf(" + 0x%x %d\n",(int)dir->fileid[0], dlen); |
|
|
|
} else printf(" - %s %d\n",dir->fileid, dlen); |
|
|
|
} |
|
|
|
} else { |
|
|
|
if(dlen == slen) { |
|
|
|
if (verbose_flag) printf(" + %s\n",dir->fileid); |
|
|
|
if (Verbose) printf(" + %s\n",dir->fileid); |
|
|
|
if(scmplen(dir->fileid, filename, slen)) { |
|
|
|
*out_dir = *dir; |
|
|
|
if(NULL != out_secnum) { |
|
|
|
*out_secnum = CdTell(isofile) - 1; |
|
|
|
} |
|
|
|
if(NULL != out_offset) { |
|
|
|
*out_offset = dirp; |
|
|
|
} |
|
|
|
return true; |
|
|
|
*out_dir = *dir; |
|
|
|
if(out_secnum != NULL) *out_secnum = CdTell(fdi) - 1; |
|
|
|
if(out_offset != NULL) *out_offset = dirp; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
dirp += dir->len; |
|
|
|
if(dirp >= 0x800) { |
|
|
|
CdRead(sec, 1, isofile); |
|
|
|
CdRead(sec, 1, fdi); |
|
|
|
dirp = dirp % 0x800; |
|
|
|
} |
|
|
|
dir = (iso_directory_t*)(sec + dirp); |
|
|
|
dir = (iso_rep_t*)(sec + dirp); |
|
|
|
} |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
bool CdFindFile(iso_directory_t *outdir, FILE *isofile, const char *filename, loc_t *out_secnum, loc_t *out_offset) |
|
|
|
bool CdFindFile(iso_rep_t *outdir, FILE *fdi, const char *filename, loc_t *out_secnum, loc_t *out_offset) |
|
|
|
{ |
|
|
|
const char *next; |
|
|
|
const char *cur = filename; |
|
|
|
int slen; |
|
|
|
if (verbose_flag) printf("> %s\n",filename); |
|
|
|
if (Verbose) printf("> %s\n",filename); |
|
|
|
do { |
|
|
|
next = strchr(cur, '/'); |
|
|
|
if(next == NULL) { |
|
|
|
slen = strlen(cur); |
|
|
|
} else { |
|
|
|
slen = (int)(next - cur); |
|
|
|
} |
|
|
|
if(!CdFindFileInDir(outdir, isofile, cur, slen, out_secnum, out_offset)) |
|
|
|
return false; |
|
|
|
if(next != NULL) { |
|
|
|
CdSetloc(isofile, outdir->lba); |
|
|
|
next++; cur = next; |
|
|
|
} else break; |
|
|
|
if(next == NULL) slen = strlen(cur); |
|
|
|
else slen = (int)(next - cur); |
|
|
|
if (!CdFindFileInDir(outdir, fdi, cur, slen, out_secnum, out_offset)) |
|
|
|
return false; |
|
|
|
if (next != NULL) { |
|
|
|
CdSetloc(fdi, outdir->lba); |
|
|
|
next++; cur = next; |
|
|
|
} else break; |
|
|
|
} while(next != NULL); |
|
|
|
return true; |
|
|
|
} |
|
|
@@ -178,7 +164,7 @@ bool CdFindFile(iso_directory_t *outdir, FILE *isofile, const char *filename, lo |
|
|
|
/* options definitions */ |
|
|
|
static int help_flag; |
|
|
|
static struct option long_options[] = { |
|
|
|
{"verbose", no_argument, &verbose_flag, 1}, |
|
|
|
{"verbose", no_argument, &Verbose, 1}, |
|
|
|
{"help", no_argument, &help_flag, 1}, |
|
|
|
{"list", no_argument, 0, 'l'}, |
|
|
|
{"put", no_argument, 0, 'p'}, |
|
|
@@ -191,7 +177,7 @@ static struct option long_options[] = { |
|
|
|
|
|
|
|
void explain(void) |
|
|
|
{ |
|
|
|
puts("Utilisation : isoupd [options] isofile"); |
|
|
|
puts("Utilisation : isoupd [options] fichier.iso"); |
|
|
|
puts(" -l, --list liste d'un repertoire (defaut)"); |
|
|
|
puts(" -p, --put modifie un fichier de l'iso"); |
|
|
|
puts(" -g, --get extrait un fichier de l'iso"); |
|
|
@@ -199,7 +185,7 @@ void explain(void) |
|
|
|
puts(" -f, --file chemin du fichier dans l'iso"); |
|
|
|
puts(" -h, --host nom du fichier host. Obligatoire pour -p et -g"); |
|
|
|
puts(" -d, --dir nom du repertoire a lister dans l'iso"); |
|
|
|
puts(" --help cette aide !"); |
|
|
|
puts(" --help affiche cette aide !"); |
|
|
|
} |
|
|
|
void messerr(char * m, int err) |
|
|
|
{ |
|
|
@@ -219,11 +205,11 @@ void errmode(char * o) |
|
|
|
int main(int N, char *P[]) |
|
|
|
{ |
|
|
|
int c, l, opt_ind = 0; |
|
|
|
FILE *hostfile, *isofile; |
|
|
|
FILE *fdh, *fdi; |
|
|
|
char etoile[2] = "*"; |
|
|
|
|
|
|
|
if(sizeof(iso_directory_t) != 33) { |
|
|
|
fprintf(stderr, "Mauvaise compilation : tid=%lu\n",sizeof(iso_directory_t)); |
|
|
|
if(sizeof(iso_rep_t) != 33) { |
|
|
|
fprintf(stderr, "Mauvaise compilation : tid=%lu\n",sizeof(iso_rep_t)); |
|
|
|
return 9; |
|
|
|
} |
|
|
|
while (1) { |
|
|
@@ -237,19 +223,19 @@ char etoile[2] = "*"; |
|
|
|
break; |
|
|
|
|
|
|
|
case 'l': |
|
|
|
if (mode_flag != -2) errmode(P[opt_ind]); |
|
|
|
mode_flag=0; |
|
|
|
if (Mode != -2) errmode(P[opt_ind]); |
|
|
|
Mode=0; |
|
|
|
break; |
|
|
|
case 'p': |
|
|
|
if (mode_flag != -2) errmode(P[opt_ind]); |
|
|
|
mode_flag=1; |
|
|
|
if (Mode != -2) errmode(P[opt_ind]); |
|
|
|
Mode=1; |
|
|
|
break; |
|
|
|
case 'g': |
|
|
|
if (mode_flag != -2) errmode(P[opt_ind]); |
|
|
|
mode_flag=-1; |
|
|
|
if (Mode != -2) errmode(P[opt_ind]); |
|
|
|
Mode=-1; |
|
|
|
break; |
|
|
|
case 'v': |
|
|
|
verbose_flag=1; |
|
|
|
Verbose=1; |
|
|
|
break; |
|
|
|
case 'h': |
|
|
|
hostfilename = optarg; |
|
|
@@ -287,135 +273,133 @@ char etoile[2] = "*"; |
|
|
|
} |
|
|
|
/* verifications */ |
|
|
|
if (! isofilename) messerr("Fichier ISO absent",2); |
|
|
|
if (mode_flag == -2) mode_flag = 0; /* defaut */ |
|
|
|
switch(mode_flag) { |
|
|
|
if (Mode == -2) Mode = 0; /* defaut */ |
|
|
|
switch(Mode) { |
|
|
|
case 0 : /* list */ |
|
|
|
if (targetfilename) messerr("option -f inutile",2); |
|
|
|
if (hostfilename) messerr("option -h inutile",2); |
|
|
|
if (!targetdirname) targetdirname = etoile; |
|
|
|
if (verbose_flag) printf("Liste de %s dans %s\n",targetdirname,isofilename); |
|
|
|
if (Verbose) printf("Liste de %s dans %s\n",targetdirname,isofilename); |
|
|
|
targetfilename = targetdirname; |
|
|
|
break; |
|
|
|
case 1 : /* put */ |
|
|
|
if (targetdirname) messerr("option -d inutile",2); |
|
|
|
if (!targetfilename) messerr("Chemin du fichier dans l'ISO absent",2); |
|
|
|
if (!hostfilename) messerr("fichier host source absent",2); |
|
|
|
if (verbose_flag) printf("PUT de %s vers %s dans %s\n",hostfilename,targetfilename,isofilename); |
|
|
|
if (Verbose) printf("PUT de %s vers %s dans %s\n",hostfilename,targetfilename,isofilename); |
|
|
|
break; |
|
|
|
case -1 : /* get */ |
|
|
|
if (targetdirname) messerr("option -d inutile",2); |
|
|
|
if (!targetfilename) messerr("Chemin du fichier dans l'ISO absent",2); |
|
|
|
if (!hostfilename) messerr("fichier host destination absent",2); |
|
|
|
if (verbose_flag) printf("GET de %s dans %s vers %s\n",targetfilename,isofilename,hostfilename); |
|
|
|
if (Verbose) printf("GET de %s dans %s vers %s\n",targetfilename,isofilename,hostfilename); |
|
|
|
break; |
|
|
|
} |
|
|
|
if (verbose_flag) printf("Verbose : mode = %d\n",mode_flag); |
|
|
|
if (Verbose) printf("Verbose : mode = %d\n",Mode); |
|
|
|
|
|
|
|
if ((isofile = fopen(isofilename, "r+")) == NULL) { |
|
|
|
if ((fdi = fopen(isofilename, "r+")) == NULL) { |
|
|
|
fprintf(stderr, "Erreur ouverture ISO %s\n", isofilename); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
if(hostfilename != NULL) { |
|
|
|
if ((hostfile = fopen(hostfilename, "r")) == NULL) { |
|
|
|
if (mode_flag == 1) { /* put */ |
|
|
|
if ((fdh = fopen(hostfilename, "r")) == NULL) { |
|
|
|
if (Mode == 1) { /* put */ |
|
|
|
fprintf(stderr, "Erreur ouverture fichier %s\n", hostfilename); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
} else { |
|
|
|
if (mode_flag == -1) { /* get */ |
|
|
|
if (Mode == -1) { /* get */ |
|
|
|
fprintf(stderr,"Erreur : le fichier %s existe deja !\n",hostfilename); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
} |
|
|
|
if (mode_flag == -1) { /* get */ |
|
|
|
if ((hostfile = fopen(hostfilename, "w")) == NULL) { |
|
|
|
if (Mode == -1) { /* get */ |
|
|
|
if ((fdh = fopen(hostfilename, "w")) == NULL) { |
|
|
|
fprintf(stderr, "Erreur creation fichier %s\n", hostfilename); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
byte sec[CD_SECTOR_SIZE]; |
|
|
|
iso_directory_t *dir = (iso_directory_t*)(sec); |
|
|
|
CdSetloc(isofile, ISO_PADSIZE); |
|
|
|
CdRead(sec, 1, isofile); |
|
|
|
iso_rep_t *dir = (iso_rep_t*)(sec); |
|
|
|
CdSetloc(fdi, ISO_PADSIZE); |
|
|
|
CdRead(sec, 1, fdi); |
|
|
|
if(!ispvd(sec)) { |
|
|
|
fprintf(stderr, "%s n'est pas un fichier ISO\n", isofilename); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
loc_t root_lba = *(loc_t*)(sec+158); |
|
|
|
if (verbose_flag) printf("root lba = %x\n", root_lba); |
|
|
|
CdSetloc(isofile, root_lba); |
|
|
|
if (Verbose) printf("root lba = %x\n", root_lba); |
|
|
|
CdSetloc(fdi, root_lba); |
|
|
|
loc_t dir_lba, dir_offset; |
|
|
|
bool s = CdFindFile(dir, isofile, targetfilename, &dir_lba, &dir_offset); |
|
|
|
if (!mode_flag) { /* list */ |
|
|
|
fclose(isofile); |
|
|
|
bool s = CdFindFile(dir, fdi, targetfilename, &dir_lba, &dir_offset); |
|
|
|
if (!Mode) { /* list */ |
|
|
|
fclose(fdi); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
if(!s) { |
|
|
|
fprintf(stderr, "Fichier %s absent de l'ISO %s\n", targetfilename, isofilename); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
CdSetloc(isofile, dir_lba); |
|
|
|
CdRead(sec, 1, isofile); |
|
|
|
dir = (iso_directory_t*)(sec + dir_offset); |
|
|
|
CdSetloc(fdi, dir_lba); |
|
|
|
CdRead(sec, 1, fdi); |
|
|
|
dir = (iso_rep_t*)(sec + dir_offset); |
|
|
|
int maxsize = ALIGN(dir->file_len, 0x800); |
|
|
|
printf("Taille du fichier sur l'ISO : %d\n", dir->file_len); |
|
|
|
if (mode_flag == -1) { /* get */ |
|
|
|
if (Mode == -1) { /* get */ |
|
|
|
byte *filedata = (byte*)(malloc(maxsize)); |
|
|
|
CdSetloc(isofile, dir->lba); |
|
|
|
CdRead(filedata, (maxsize / CD_SECTOR_SIZE), isofile); |
|
|
|
fwrite(filedata, 1, dir->file_len, hostfile); |
|
|
|
fclose(hostfile); |
|
|
|
fclose(isofile); |
|
|
|
CdSetloc(fdi, dir->lba); |
|
|
|
CdRead(filedata, (maxsize / CD_SECTOR_SIZE), fdi); |
|
|
|
fwrite(filedata, 1, dir->file_len, fdh); |
|
|
|
fclose(fdh); |
|
|
|
fclose(fdi); |
|
|
|
printf("Extraction faite dans %s.\n",hostfilename); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
int len = getfilesize(hostfile); |
|
|
|
int len = getfilesize(fdh); |
|
|
|
int aligned_len = ALIGN(len, 0x800); |
|
|
|
printf("Taille du fichier local : %d\n", len); |
|
|
|
printf("La commande --put n'est pas encore au point !\n"); |
|
|
|
return 0; /* test */ |
|
|
|
if(!length_override) { |
|
|
|
if(!ecrase) { |
|
|
|
if(len > maxsize) { |
|
|
|
fprintf(stderr, "Le fichier %s depasse de %d octets (%d > %d)\n", |
|
|
|
hostfilename, |
|
|
|
len - maxsize, |
|
|
|
len, maxsize |
|
|
|
); |
|
|
|
fclose(hostfile); |
|
|
|
fclose(isofile); |
|
|
|
fprintf(stderr, "Le fichier %s depasse de %d octets (%d > %d)\n", |
|
|
|
hostfilename, len - maxsize, len, maxsize); |
|
|
|
fclose(fdh); |
|
|
|
fclose(fdi); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
if((uint32_t)len != dir->file_len) { |
|
|
|
if((uint32_t)aligned_len < dir->file_len) { |
|
|
|
printf("ATTENTION: La mise en place de ce fichier va retrecir l'espace d'allocation disponible !\n"); |
|
|
|
printf(" (il sera de %d octets)\n", aligned_len); |
|
|
|
} |
|
|
|
printf("Les tailles sont differentes mais compatibles. Modification ? [o/N]\n"); |
|
|
|
int ch = getchar(); |
|
|
|
if((ch != 'o') && (ch != 'O')) { |
|
|
|
printf("Annulation !!\n"); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
if((uint32_t)aligned_len < dir->file_len) { |
|
|
|
printf("ATTENTION: La mise en place de ce fichier\n va retrecir l'espace d'allocation disponible !\n"); |
|
|
|
printf(" (il sera de %d octets)\n", aligned_len); |
|
|
|
} |
|
|
|
printf("Les tailles sont differentes mais compatibles.\n"); |
|
|
|
} |
|
|
|
} |
|
|
|
printf("AVERTISSEMENT : Version %s de test !!!\n",VERSION); |
|
|
|
printf("============= Il faut faire une sauvegarde de l'ISO avant.\n"); |
|
|
|
printf("Modification ? [o/N]\n"); |
|
|
|
int ch = getchar(); |
|
|
|
if((ch != 'o') && (ch != 'O')) { |
|
|
|
printf("Annulation !!\n"); |
|
|
|
return 1; |
|
|
|
} |
|
|
|
byte *filedata = (byte*)(malloc(aligned_len)); |
|
|
|
memset(filedata, 0, aligned_len); |
|
|
|
fread(filedata, 1, len, hostfile); |
|
|
|
fclose(hostfile); |
|
|
|
fread(filedata, 1, len, fdh); |
|
|
|
fclose(fdh); |
|
|
|
|
|
|
|
printf("Ecriture de %d octets sur le secteur %u\n", len, dir->lba); |
|
|
|
CdSetloc(isofile, dir->lba); |
|
|
|
CdWrite(filedata, (aligned_len / CD_SECTOR_SIZE), isofile); |
|
|
|
CdSetloc(fdi, dir->lba); |
|
|
|
CdWrite(filedata, (aligned_len / CD_SECTOR_SIZE), fdi); |
|
|
|
|
|
|
|
dir->file_len = len; |
|
|
|
printf("Ecriture d'un nouveau repertoire sur %u\n", dir_lba); |
|
|
|
CdSetloc(isofile, dir_lba); |
|
|
|
CdWrite(sec, 1, isofile); |
|
|
|
CdSetloc(fdi, dir_lba); |
|
|
|
CdWrite(sec, 1, fdi); |
|
|
|
|
|
|
|
printf("OK !\n"); |
|
|
|
|
|
|
|
fclose(isofile); |
|
|
|
fclose(fdi); |
|
|
|
return 0; |
|
|
|
} |
|
|
|
|