With some violence I got iso file listing working

I don't know if code is leaking or what, the c files are full with
unused code and globals and are quite dirty. But hey, it runs for meh!
This commit is contained in:
King_DuckZ 2020-03-04 01:05:50 +01:00
parent b0e2658c15
commit 17f72fcbdf
6 changed files with 400 additions and 392 deletions

View file

@ -6,229 +6,17 @@ import std.exception;
import std.conv : to; import std.conv : to;
import std.stdint; import std.stdint;
private const int MAX_ISONAME_V2 = 207; /*254 - 33 - 14 (XA Record)*/
private const int MAX_ISONAME = MAX_ISONAME_V2;
private const int ISO_MULTIEXTENT = 128; /*Not final entry of a mult. ext. file*/
private const SECTOR_SIZE = 2048;
/*
* Use sector_offset != 0 (-N #) if we have an image file
* of a single session and we need to list the directory contents.
* This is the session block (sector) number of the start
* of the session when it would be on disk.
*/
private uint sector_offset = 0;
private int ISODCL(int from, int to) pure {
return to - from + 1;
}
private int ISO_BLOCKS(size_t X) pure {
return (cast(int)X / SECTOR_SIZE + ((cast(int)X % SECTOR_SIZE) ? 1 : 0));
}
private alias off_t = long;
extern(C) { extern(C) {
struct iso_volume_descriptor { alias iso_listing_callback = int function(void*,const(char)*,int);
char[ISODCL(1, 1)] type; /* 711 */ int scan_iso (const(char)* filename, iso_listing_callback callback, void* user_data);
char[ISODCL(2, 6)] id;
char[ISODCL(7, 7)] version_;
char[ISODCL(8, 2048)] data;
}
struct iso_directory_record { private int printer(void*, const(char)* path, int is_dir) {
byte [ISODCL(1, 1)] length; /* 711 */ writef("Entry \"%s\"", path.fromStringz);
char [ISODCL(2, 2)] ext_attr_length; /* 711 */ if (is_dir != 0) {
char [ISODCL(3, 10)] extent; /* 733 */ write(" (directory)");
char [ISODCL(11, 18)] size; /* 733 */ }
char [ISODCL(19, 25)] date; /* 7 by 711 */ write("\n");
byte [ISODCL(26, 26)] flags; return 0;
char [ISODCL(27, 27)] file_unit_size; /* 711 */
char [ISODCL(28, 28)] interleave; /* 711 */
char [ISODCL(29, 32)] volume_sequence_number; /* 723 */
byte [ISODCL(33, 33)] name_len; /* 711 */
char [MAX_ISONAME+1] name; /* Not really, but we need something here */
};
version(USE_SCG) {
int readsecs (uint32_t startsecno, void* buffer, int sectorcount);
}
}
private struct todo {
todo* next;
todo* prev;
string name;
int extent;
int length;
}
//int extent; /* Directory extent */
//int len; /* Directory size */
private void parse_dir(todo* dp, string rootname, int extent, int len) {
todo td;
int i;
iso_directory_record* idr;
iso_directory_record didr;
//stat dstat;
byte[2048] cl_buffer;
byte flags = 0;
long size = 0;
int sextent = 0;
int rlen;
int blen;
int rr_flags = 0;
static char* n = null;
static int nlen = 0;
byte[2048] buffer;
while (len > 0) {
version(USE_SCG) {
readsecs(extent - sector_offset, buffer.ptr, ISO_BLOCKS(buffer.length));
}
else {
lseek(fileno(infile), (cast(off_t)(extent - sector_offset)) << 11, SEEK_SET);
read(fileno(infile), buffer, sizeof (buffer));
}
len -= typeof(buffer).sizeof;
extent++;
i = 0;
/*
while (true) {
idr = cast(iso_directory_record*)&buffer[i];
if (idr->length[0] == 0)
break;
parse_de(idr);
if (use_rock) {
rr_flags = dump_rr(idr);
if (rr_flags & RR_FLAG_CL) {
// Need to reparse the child link
// but note that we parse "CL/."
// so we get no usable file name.
idr = (struct iso_directory_record *) cl_buffer;
parse_cl_dir(idr, cl_extent);
} else if (rr_flags & RR_FLAG_RE)
goto cont; // skip rr_moved
}
if (Xtract &&
(idr->flags[0] & 2) != 0 &&
idr->name_len[0] == 1 &&
idr->name[0] == 0) {
// The '.' entry.
didr = *idr;
dstat = fstat_buf;
}
blen = strlen(name_buf);
blen = rlen + blen + 1;
if (nlen < blen) {
n = ___realloc(n, blen, _("find_stat name"));
nlen = blen;
}
strcatl(n, rootname, name_buf, (char *)0);
if (name_buf[0] == '.' && name_buf[1] == '\0')
n[rlen] = '\0';
if ((idr->flags[0] & 2) != 0 &&
((rr_flags & RR_FLAG_CL) ||
(idr->name_len[0] != 1 ||
(idr->name[0] != 0 && idr->name[0] != 1)))) {
// This is a plain directory (neither "xxx/."
// nor "xxx/..").
// Add this directory to the todo list.
int dir_loop = 0;
int nextent;
struct todo *tp = dp;
nextent = isonum_733((unsigned char *)idr->extent);
while (tp) {
if (tp->extent == nextent) {
dir_loop = 1;
break;
}
tp = tp->prev;
}
if (dir_loop == 0) {
td = (struct todo *) malloc(sizeof (*td));
if (td == NULL)
comerr(_("No memory.\n"));
td->next = NULL;
td->prev = dp;
td->extent = isonum_733((unsigned char *)idr->extent);
td->length = isonum_733((unsigned char *)idr->size);
td->name = (char *) malloc(strlen(rootname)
+ strlen(name_buf) + 2);
if (td->name == NULL)
comerr(_("No memory.\n"));
strcpy(td->name, rootname);
strcat(td->name, name_buf);
strcat(td->name, "/");
*todo_pp = td;
todo_pp = &td->next;
}
} else {
if (xtract && strcmp(xtract, n) == 0) {
extract_file(STDOUT_FILENO, idr, "stdout");
}
}
if (do_f &&
(idr->name_len[0] != 1 ||
(idr->name[0] != 0 && idr->name[0] != 1))) {
printf("%s\n", n);
}
if (do_listing || Xtract || do_find) {
// In case if a multi-extent file, remember the
// start extent number.
if ((idr->flags[0] & ISO_MULTIEXTENT) && size == 0)
sextent = isonum_733((unsigned char *)idr->extent);
if (debug ||
((idr->flags[0] & ISO_MULTIEXTENT) == 0 && size == 0)) {
if (dump_stat(rootname, idr, n,
isonum_733((unsigned char *)idr->extent))) {
if (Xtract) {
if ((idr->flags[0] & 2) != 0 &&
idr->name_len[0] != 1 &&
idr->name[0] != 1) {
char *p = n;
if (*p == '/')
p++;
makedirs(p,
S_IRUSR|S_IWUSR|S_IXUSR|
S_IRGRP|S_IWGRP|S_IXGRP|
S_IROTH|S_IWOTH|S_IXOTH,
FALSE);
} else {
if (myuid != 0 &&
S_ISDIR(fstat_buf.st_mode)) {
fstat_buf.st_mode |= S_IWUSR;
}
extract(rootname, idr, n);
}
}
}
} else if (Xtract && find_stat(rootname, idr, n, sextent)) {
// Extract all multi extent files here...
extract(rootname, idr, n);
}
size += fstat_buf.st_size;
if ((flags & ISO_MULTIEXTENT) &&
(idr->flags[0] & ISO_MULTIEXTENT) == 0) {
fstat_buf.st_size = size;
if (!debug)
idr->flags[0] |= ISO_MULTIEXTENT;
dump_stat(rootname, idr, n, sextent);
if (!debug)
idr->flags[0] &= ~ISO_MULTIEXTENT;
}
flags = idr->flags[0];
if ((idr->flags[0] & ISO_MULTIEXTENT) == 0)
size = 0;
}
cont:
i += buffer[i];
if (i > 2048 - offsetof(struct iso_directory_record, name[0])) break;
} */
} }
} }
@ -239,6 +27,8 @@ public string iso_to_serial (string path) {
// NPJH-50465|0D506D389F2AA444|0001|G // NPJH-50465|0D506D389F2AA444|0001|G
// ULJM-05530|5A2E0CF722EF6299|0001|G // ULJM-05530|5A2E0CF722EF6299|0001|G
scan_iso(path.toStringz, &printer, null);
return "UCES-00356"; //Tekken Dark Resurrection return "UCES-00356"; //Tekken Dark Resurrection
//return "NPJH-50465"; //Hatsune Miku (missing from redump list) //return "NPJH-50465"; //Hatsune Miku (missing from redump list)
//return "ULJM-05530"; //Undead Knights (missing from redump list) //return "ULJM-05530"; //Undead Knights (missing from redump list)

View file

@ -24,12 +24,16 @@ add_project_arguments(
c_compiler = meson.get_compiler('c') c_compiler = meson.get_compiler('c')
cdrdeflt_dep = c_compiler.find_library('cdrdeflt') cdrdeflt_dep = c_compiler.find_library('cdrdeflt')
scgcmd_dep = c_compiler.find_library('scgcmd')
schily_dep = c_compiler.find_library('schily')
scg_dep = c_compiler.find_library('scg')
siconv_dep = c_compiler.find_library('siconv')
public_inc = include_directories('include') public_inc = include_directories('include')
libisoinfo = static_library(meson.project_name(), libisoinfo = static_library(meson.project_name(),
'src/isoinfo.c', 'src/isoinfo.c',
'src/scsi.c', 'src/scsi.c',
dependencies: [cdrdeflt_dep], dependencies: [cdrdeflt_dep, scgcmd_dep, schily_dep, scg_dep, siconv_dep],
install: false, install: false,
) )

View file

@ -119,8 +119,14 @@
#define GET_UBYTE(a) a_to_u_byte(a) #define GET_UBYTE(a) a_to_u_byte(a)
#define infile in_image typedef int(*iso_listing_callback)(void*,const char*,int is_dir);
EXPORT FILE *infile = NULL;
enum ScanRetCode {
ScanRetCode_Ok = 100,
ScanRetCode_Disabled,
ScanRetCode_BadInput
};
EXPORT BOOL ignerr = FALSE; EXPORT BOOL ignerr = FALSE;
LOCAL int use_rock = 0; LOCAL int use_rock = 0;
LOCAL int use_joliet = 0; LOCAL int use_joliet = 0;
@ -174,30 +180,35 @@ LOCAL struct todo **todo_pp = &todo_idr;
LOCAL int isonum_731 __PR((char * p)); LOCAL int isonum_731 __PR((char * p));
LOCAL int isonum_733 __PR((unsigned char * p)); LOCAL int isonum_733 __PR((unsigned char * p));
LOCAL int parse_rr __PR((unsigned char * pnt, int len, LOCAL int parse_rr __PR((struct scsi_dev *dev, unsigned char * pnt,
int cont_flag)); int len, int cont_flag));
LOCAL void find_rr __PR((struct iso_directory_record * idr, LOCAL void find_rr __PR((struct iso_directory_record * idr,
Uchar **pntp, int *lenp)); Uchar **pntp, int *lenp));
LOCAL int dump_rr __PR((struct iso_directory_record * idr)); LOCAL int dump_rr __PR((struct scsi_dev *dev,
struct iso_directory_record * idr));
LOCAL BOOL dump_stat __PR((char *rootname, LOCAL BOOL dump_stat __PR((char *rootname,
struct iso_directory_record * idr, struct iso_directory_record * idr,
char *fname, char *fname,
int extent)); int extent));
LOCAL void extract __PR((char *rootname, LOCAL void extract __PR((struct scsi_dev *dev,
char *rootname, struct iso_directory_record * idr,
char *fname));
LOCAL void extract_file __PR((struct scsi_dev *dev, int f,
struct iso_directory_record * idr, struct iso_directory_record * idr,
char *fname)); char *fname));
LOCAL void extract_file __PR((int f, LOCAL void parse_cl_dir __PR((struct scsi_dev *dev,
struct iso_directory_record * idr, struct iso_directory_record *idr, int extent));
char *fname));
LOCAL void parse_cl_dir __PR((struct iso_directory_record *idr,
int extent));
LOCAL BOOL parse_de __PR((struct iso_directory_record *idr)); LOCAL BOOL parse_de __PR((struct iso_directory_record *idr));
LOCAL void parse_dir __PR((struct todo *dp, LOCAL void parse_dir __PR((struct scsi_dev *dev, struct todo *dp,
char * rootname, int extent, int len)); char * rootname, int extent, int len,
iso_listing_callback callback, void* user_data));
LOCAL void list_locales __PR((void)); LOCAL void list_locales __PR((void));
LOCAL int time_cvt __PR((unsigned char *dp, int len)); LOCAL int time_cvt __PR((unsigned char *dp, int len));
LOCAL time_t iso9660_time __PR((unsigned char *date, int *hsecp, LOCAL time_t iso9660_time __PR((unsigned char *date, int *hsecp,
BOOL longfmt)); BOOL longfmt));
LOCAL int run_scanning __PR((struct scsi_dev *dev,
iso_listing_callback callback, void *user_data));
LOCAL char* default_charset __PR((void));
LOCAL int LOCAL int
isonum_731(p) isonum_731(p)
@ -225,7 +236,8 @@ isonum_733(p)
#endif #endif
LOCAL int LOCAL int
parse_rr(pnt, len, cont_flag) parse_rr(dev, pnt, len, cont_flag)
struct scsi_dev *dev;
unsigned char *pnt; unsigned char *pnt;
int len; int len;
int cont_flag; int cont_flag;
@ -409,12 +421,12 @@ parse_rr(pnt, len, cont_flag)
unsigned char sector[2048]; unsigned char sector[2048];
#ifdef USE_SCG #ifdef USE_SCG
readsecs(cont_extent - sector_offset, sector, ISO_BLOCKS(sizeof (sector))); readsecs(dev, cont_extent - sector_offset, sector, ISO_BLOCKS(sizeof (sector)));
#else #else
lseek(fileno(infile), ((off_t)(cont_extent - sector_offset)) << 11, SEEK_SET); lseek(fileno(infile), ((off_t)(cont_extent - sector_offset)) << 11, SEEK_SET);
read(fileno(infile), sector, sizeof (sector)); read(fileno(infile), sector, sizeof (sector));
#endif #endif
flag2 |= parse_rr(&sector[cont_offset], cont_size, 1); flag2 |= parse_rr(dev, &sector[cont_offset], cont_size, 1);
} }
/* /*
* for symbolic links, strip out the last '/' * for symbolic links, strip out the last '/'
@ -461,14 +473,15 @@ find_rr(idr, pntp, lenp)
} }
LOCAL int LOCAL int
dump_rr(idr) dump_rr(dev, idr)
struct scsi_dev *dev;
struct iso_directory_record *idr; struct iso_directory_record *idr;
{ {
int len; int len;
unsigned char * pnt; unsigned char * pnt;
find_rr(idr, &pnt, &len); find_rr(idr, &pnt, &len);
return (parse_rr(pnt, len, 0)); return (parse_rr(dev, pnt, len, 0));
} }
LOCAL char *months[12] = {"Jan", "Feb", "Mar", "Apr", LOCAL char *months[12] = {"Jan", "Feb", "Mar", "Apr",
@ -572,7 +585,8 @@ dump_stat(rootname, idr, fname, extent)
} }
LOCAL void LOCAL void
extract(rootname, idr, fname) extract(dev, rootname, idr, fname)
struct scsi_dev *dev;
char *rootname; char *rootname;
struct iso_directory_record *idr; struct iso_directory_record *idr;
char *fname; char *fname;
@ -682,7 +696,7 @@ static BOOL isfirst = TRUE;
return; return;
} }
lseek(f, 0, SEEK_END); lseek(f, 0, SEEK_END);
extract_file(f, idr, fname); extract_file(dev, f, idr, fname);
if ((idr->flags[0] & ISO_MULTIEXTENT) == 0) { if ((idr->flags[0] & ISO_MULTIEXTENT) == 0) {
#ifdef HAVE_FCHOWN #ifdef HAVE_FCHOWN
fchown(f, fstat_buf.st_uid, fstat_buf.st_gid); fchown(f, fstat_buf.st_uid, fstat_buf.st_gid);
@ -720,7 +734,8 @@ setmode:
} }
LOCAL void LOCAL void
extract_file(f, idr, fname) extract_file(dev, f, idr, fname)
struct scsi_dev *dev;
int f; int f;
struct iso_directory_record *idr; struct iso_directory_record *idr;
char *fname; char *fname;
@ -737,7 +752,7 @@ extract_file(f, idr, fname)
while (len > 0) { while (len > 0) {
tlen = (len > sizeof (buff) ? sizeof (buff) : len); tlen = (len > sizeof (buff) ? sizeof (buff) : len);
#ifdef USE_SCG #ifdef USE_SCG
readsecs(extent - sector_offset, buff, ISO_BLOCKS(tlen)); readsecs(dev, extent - sector_offset, buff, ISO_BLOCKS(tlen));
#else #else
lseek(fileno(infile), ((off_t)(extent - sector_offset)) << 11, SEEK_SET); lseek(fileno(infile), ((off_t)(extent - sector_offset)) << 11, SEEK_SET);
read(fileno(infile), buff, tlen); read(fileno(infile), buff, tlen);
@ -751,7 +766,8 @@ extract_file(f, idr, fname)
LOCAL void LOCAL void
parse_cl_dir(idr, extent) parse_cl_dir(dev, idr, extent)
struct scsi_dev *dev;
struct iso_directory_record *idr; struct iso_directory_record *idr;
int extent; int extent;
{ {
@ -759,14 +775,14 @@ parse_cl_dir(idr, extent)
strlcpy(cl_name_buf, name_buf, sizeof (cl_name_buf)); strlcpy(cl_name_buf, name_buf, sizeof (cl_name_buf));
#ifdef USE_SCG #ifdef USE_SCG
readsecs(extent - sector_offset, idr, 1); readsecs(dev, extent - sector_offset, idr, 1);
#else #else
lseek(fileno(infile), ((off_t)(extent - sector_offset)) << 11, SEEK_SET); lseek(fileno(infile), ((off_t)(extent - sector_offset)) << 11, SEEK_SET);
read(fileno(infile), idr, 2048); read(fileno(infile), idr, 2048);
#endif #endif
if (parse_de(idr) && use_rock) if (parse_de(idr) && use_rock)
dump_rr(idr); dump_rr(dev, idr);
strlcpy(name_buf, cl_name_buf, sizeof (name_buf)); strlcpy(name_buf, cl_name_buf, sizeof (name_buf));
} }
@ -887,11 +903,14 @@ parse_de(idr)
} }
LOCAL void LOCAL void
parse_dir(dp, rootname, extent, len) parse_dir(dev, dp, rootname, extent, len, callback, user_data)
struct scsi_dev *dev;
struct todo *dp; struct todo *dp;
char *rootname; char *rootname;
int extent; /* Directory extent */ int extent; /* Directory extent */
int len; /* Directory size */ int len; /* Directory size */
iso_listing_callback callback;
void *user_data;
{ {
struct todo *td; struct todo *td;
int i; int i;
@ -910,7 +929,7 @@ static int nlen = 0;
while (len > 0) { while (len > 0) {
#ifdef USE_SCG #ifdef USE_SCG
readsecs(extent - sector_offset, buffer, ISO_BLOCKS(sizeof (buffer))); readsecs(dev, extent - sector_offset, buffer, ISO_BLOCKS(sizeof (buffer)));
#else #else
lseek(fileno(infile), ((off_t)(extent - sector_offset)) << 11, SEEK_SET); lseek(fileno(infile), ((off_t)(extent - sector_offset)) << 11, SEEK_SET);
read(fileno(infile), buffer, sizeof (buffer)); read(fileno(infile), buffer, sizeof (buffer));
@ -924,7 +943,7 @@ static int nlen = 0;
break; break;
parse_de(idr); parse_de(idr);
if (use_rock) { if (use_rock) {
rr_flags = dump_rr(idr); rr_flags = dump_rr(dev, idr);
if (rr_flags & RR_FLAG_CL) { if (rr_flags & RR_FLAG_CL) {
/* /*
@ -933,7 +952,7 @@ static int nlen = 0;
* so we get no usable file name. * so we get no usable file name.
*/ */
idr = (struct iso_directory_record *) cl_buffer; idr = (struct iso_directory_record *) cl_buffer;
parse_cl_dir(idr, cl_extent); parse_cl_dir(dev, idr, cl_extent);
} else if (rr_flags & RR_FLAG_RE) } else if (rr_flags & RR_FLAG_RE)
goto cont; /* skip rr_moved */ goto cont; /* skip rr_moved */
} }
@ -969,6 +988,8 @@ static int nlen = 0;
int nextent; int nextent;
struct todo *tp = dp; struct todo *tp = dp;
(*callback)(user_data, n, 1);
nextent = isonum_733((unsigned char *)idr->extent); nextent = isonum_733((unsigned char *)idr->extent);
while (tp) { while (tp) {
if (tp->extent == nextent) { if (tp->extent == nextent) {
@ -996,9 +1017,13 @@ static int nlen = 0;
*todo_pp = td; *todo_pp = td;
todo_pp = &td->next; todo_pp = &td->next;
} }
} else if ((idr->flags[0] & 2) &&
(idr->name[0] != 0 || idr->name[0] != 1)) {
/* this is . or .. */
} else { } else {
callback(user_data, n, 0);
if (xtract && strcmp(xtract, n) == 0) { if (xtract && strcmp(xtract, n) == 0) {
extract_file(STDOUT_FILENO, idr, "stdout"); extract_file(dev, STDOUT_FILENO, idr, "stdout");
} }
} }
if (do_f && if (do_f &&
@ -1035,7 +1060,7 @@ static int nlen = 0;
S_ISDIR(fstat_buf.st_mode)) { S_ISDIR(fstat_buf.st_mode)) {
fstat_buf.st_mode |= S_IWUSR; fstat_buf.st_mode |= S_IWUSR;
} }
extract(rootname, idr, n); extract(dev, rootname, idr, n);
} }
} }
} }
@ -1043,7 +1068,7 @@ static int nlen = 0;
/* /*
* Extract all multi extent files here... * Extract all multi extent files here...
*/ */
extract(rootname, idr, n); extract(dev, rootname, idr, n);
} }
size += fstat_buf.st_size; size += fstat_buf.st_size;
if ((flags & ISO_MULTIEXTENT) && if ((flags & ISO_MULTIEXTENT) &&
@ -1073,14 +1098,66 @@ static int nlen = 0;
} }
EXPORT int EXPORT int
main(argc, argv) scan_iso (filename, callback, user_data)
int argc; const char* filename;
char *argv[]; iso_listing_callback callback;
void* user_data;
{
struct scsi_dev *dev;
int retval;
if (NULL == filename || NULL == callback)
return ScanRetCode_BadInput;
dev = scsidev_file_open(filename);
retval = run_scanning(dev, callback, user_data);
scsidev_close(dev);
return retval;
}
EXPORT int
scan_device (sdevname, callback, user_data)
const char* sdevname;
iso_listing_callback callback;
void* user_data;
{
#ifndef USE_SCG
return ScanRetCode_Disabled;
#else
struct scsi_dev *dev;
int retval;
char* devname;
if (NULL == callback)
return ScanRetCode_BadInput;
if (sdevname == NULL)
cdr_defaults(&devname, NULL, NULL, NULL, NULL);
if (devname == NULL)
return ScanRetCode_BadInput;
dev = scsidev_open(devname);
if (scsidev_has_error(dev)) {
retval = scsidev_error_code(dev);
scsidev_close(dev);
return retval;
}
retval = run_scanning(dev, callback, user_data);
scsidev_close(dev);
return retval;
#endif
}
LOCAL int
run_scanning(dev, callback, user_data)
struct scsi_dev *dev;
iso_listing_callback callback;
void *user_data;
{ {
int c; int c;
int ret = 0; int ret = 0;
char *filename = NULL;
char *sdevname = NULL;
#if defined(USE_NLS) #if defined(USE_NLS)
char *dir; char *dir;
#endif #endif
@ -1120,63 +1197,7 @@ main(argc, argv)
myuid = getuid(); myuid = getuid();
#if defined(USE_NLS) && defined(HAVE_NL_LANGINFO) && defined(CODESET) charset = default_charset();
/*
* If the locale has not been set up, nl_langinfo() returns the
* name of the default codeset. This should be either "646",
* "ISO-646", "ASCII", or something similar. Unfortunately, the
* POSIX standard does not include a list of valid locale names,
* so ne need to find all values in use.
*
* Observed:
* Solaris "646"
* Linux "ANSI_X3.4-1968" strange value from Linux...
*/
if (charset == NULL) {
char *codeset = nl_langinfo(CODESET);
Uchar *p;
if (codeset != NULL)
codeset = strdup(codeset);
if (codeset == NULL) /* Should not happen */
goto setcharset;
if (*codeset == '\0') /* Invalid locale */
goto setcharset;
for (p = (Uchar *)codeset; *p != '\0'; p++) {
if (islower(*p))
*p = toupper(*p);
}
p = (Uchar *)strstr(codeset, "ISO");
if (p != NULL) {
if (*p == '_' || *p == '-')
p++;
codeset = (char *)p;
}
if (strcmp("646", codeset) != 0 &&
strcmp("ASCII", codeset) != 0 &&
strcmp("US-ASCII", codeset) != 0 &&
strcmp("US_ASCII", codeset) != 0 &&
strcmp("USASCII", codeset) != 0 &&
strcmp("ANSI_X3.4-1968", codeset) != 0)
charset = nl_langinfo(CODESET);
if (codeset != NULL)
free(codeset);
#define verbose 1
if (verbose > 0 && charset != NULL) {
error(_("Setting input-charset to '%s' from locale.\n"),
charset);
}
}
setcharset:
/*
* Allow to switch off locale with -input-charset "".
*/
if (charset != NULL && *charset == '\0')
charset = NULL;
#endif
if (charset == NULL) { if (charset == NULL) {
#if (defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(__DJGPP__) || defined(__MINGW32__)) && !defined(IS_CYGWIN_1) #if (defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(__DJGPP__) || defined(__MINGW32__)) && !defined(IS_CYGWIN_1)
@ -1197,38 +1218,11 @@ setcharset:
exit(1); exit(1);
} }
if (filename != NULL && sdevname != NULL) {
errmsgno(EX_BAD, _("Only one of -i or dev= allowed\n"));
}
#ifdef USE_SCG
if (filename == NULL && sdevname == NULL)
cdr_defaults(&sdevname, NULL, NULL, NULL, NULL);
#endif
if (filename == NULL && sdevname == NULL) {
fprintf(stderr, _("ISO-9660 image not specified\n"));
}
if (filename != NULL)
infile = fopen(filename, "rb");
else
filename = sdevname;
if (infile != NULL) {
/* EMPTY */;
#ifdef USE_SCG
} else if (scsidev_open(filename) < 0) {
#else
} else {
#endif
fprintf(stderr, _("Unable to open %s\n"), filename);
exit(1);
}
/* /*
* Absolute sector offset, so don't subtract sector_offset here. * Absolute sector offset, so don't subtract sector_offset here.
*/ */
#ifdef USE_SCG #ifdef USE_SCG
readsecs(16 + toc_offset, &ipd, ISO_BLOCKS(sizeof (ipd))); readsecs(dev, 16 + toc_offset, &ipd, ISO_BLOCKS(sizeof (ipd)));
#else #else
lseek(fileno(infile), ((off_t)(16 + toc_offset)) <<11, SEEK_SET); lseek(fileno(infile), ((off_t)(16 + toc_offset)) <<11, SEEK_SET);
read(fileno(infile), &ipd, sizeof (ipd)); read(fileno(infile), &ipd, sizeof (ipd));
@ -1240,7 +1234,7 @@ setcharset:
c = 17; c = 17;
do { do {
#ifdef USE_SCG #ifdef USE_SCG
readsecs(c + toc_offset, &jpd, ISO_BLOCKS(sizeof (jpd))); readsecs(dev, c + toc_offset, &jpd, ISO_BLOCKS(sizeof (jpd)));
#else #else
lseek(fileno(infile), ((off_t)(c + toc_offset)) <<11, SEEK_SET); lseek(fileno(infile), ((off_t)(c + toc_offset)) <<11, SEEK_SET);
read(fileno(infile), &jpd, sizeof (jpd)); read(fileno(infile), &jpd, sizeof (jpd));
@ -1248,7 +1242,7 @@ setcharset:
} while (++c < 32 && GET_UBYTE(jpd.type) != ISO_VD_END); } while (++c < 32 && GET_UBYTE(jpd.type) != ISO_VD_END);
if (GET_UBYTE(jpd.type) == ISO_VD_END) do { if (GET_UBYTE(jpd.type) == ISO_VD_END) do {
#ifdef USE_SCG #ifdef USE_SCG
readsecs(c + toc_offset, &jpd, ISO_BLOCKS(sizeof (jpd))); readsecs(dev, c + toc_offset, &jpd, ISO_BLOCKS(sizeof (jpd)));
#else #else
lseek(fileno(infile), ((off_t)(c + toc_offset)) <<11, SEEK_SET); lseek(fileno(infile), ((off_t)(c + toc_offset)) <<11, SEEK_SET);
read(fileno(infile), &jpd, sizeof (jpd)); read(fileno(infile), &jpd, sizeof (jpd));
@ -1274,12 +1268,12 @@ setcharset:
*/ */
extent = isonum_733((unsigned char *)idr->extent); extent = isonum_733((unsigned char *)idr->extent);
#ifdef USE_SCG #ifdef USE_SCG
readsecs(extent - sector_offset, buffer, ISO_BLOCKS(sizeof (buffer))); readsecs(dev, extent - sector_offset, buffer, ISO_BLOCKS(sizeof (buffer)));
#else #else
lseek(fileno(infile), ((off_t)(extent - sector_offset)) <<11, SEEK_SET); lseek(fileno(infile), ((off_t)(extent - sector_offset)) <<11, SEEK_SET);
read(fileno(infile), buffer, sizeof (buffer)); read(fileno(infile), buffer, sizeof (buffer));
#endif #endif
c = dump_rr((struct iso_directory_record *) buffer); c = dump_rr(dev, (struct iso_directory_record *) buffer);
if (c == 0 || if (c == 0 ||
(c & (RR_FLAG_SP | RR_FLAG_ER)) == 0 || su_version < 1 || rr_version < 1) { (c & (RR_FLAG_SP | RR_FLAG_ER)) == 0 || su_version < 1 || rr_version < 1) {
if (!debug) if (!debug)
@ -1324,7 +1318,7 @@ setcharset:
block++; block++;
#ifdef USE_SCG #ifdef USE_SCG
readsecs(block + toc_offset, &jpd, ISO_BLOCKS(sizeof (jpd))); readsecs(dev, block + toc_offset, &jpd, ISO_BLOCKS(sizeof (jpd)));
#else #else
lseek(fileno(infile), lseek(fileno(infile),
((off_t)(block + toc_offset)) <<11, SEEK_SET); ((off_t)(block + toc_offset)) <<11, SEEK_SET);
@ -1363,17 +1357,15 @@ setcharset:
if (use_joliet) if (use_joliet)
idr = (struct iso_directory_record *)jpd.root_directory_record; idr = (struct iso_directory_record *)jpd.root_directory_record;
parse_dir(todo_idr, "/", isonum_733((unsigned char *)idr->extent), parse_dir(dev, todo_idr, "/", isonum_733((unsigned char *)idr->extent),
isonum_733((unsigned char *)idr->size)); isonum_733((unsigned char *)idr->size), callback, user_data);
td = todo_idr; td = todo_idr;
while (td) { while (td) {
parse_dir(td, td->name, td->extent, td->length); parse_dir(dev, td, td->name, td->extent, td->length, callback, user_data);
free(td->name); free(td->name);
td = td->next; td = td->next;
} }
if (infile != NULL)
fclose(infile);
return (ret); return (ret);
} }
@ -1468,3 +1460,68 @@ iso9660_time(date, hsecp, longfmt)
t -= gmtoff * 15 * 60; t -= gmtoff * 15 * 60;
return (t); return (t);
} }
LOCAL char*
default_charset(void)
{
char *charset = NULL;
#if defined(USE_NLS) && defined(HAVE_NL_LANGINFO) && defined(CODESET)
/*
* If the locale has not been set up, nl_langinfo() returns the
* name of the default codeset. This should be either "646",
* "ISO-646", "ASCII", or something similar. Unfortunately, the
* POSIX standard does not include a list of valid locale names,
* so ne need to find all values in use.
*
* Observed:
* Solaris "646"
* Linux "ANSI_X3.4-1968" strange value from Linux...
*/
if (charset == NULL) {
char *codeset = nl_langinfo(CODESET);
Uchar *p;
if (codeset != NULL)
codeset = strdup(codeset);
if (codeset == NULL) /* Should not happen */
goto setcharset;
if (*codeset == '\0') /* Invalid locale */
goto setcharset;
for (p = (Uchar *)codeset; *p != '\0'; p++) {
if (islower(*p))
*p = toupper(*p);
}
p = (Uchar *)strstr(codeset, "ISO");
if (p != NULL) {
if (*p == '_' || *p == '-')
p++;
codeset = (char *)p;
}
if (strcmp("646", codeset) != 0 &&
strcmp("ASCII", codeset) != 0 &&
strcmp("US-ASCII", codeset) != 0 &&
strcmp("US_ASCII", codeset) != 0 &&
strcmp("USASCII", codeset) != 0 &&
strcmp("ANSI_X3.4-1968", codeset) != 0)
charset = nl_langinfo(CODESET);
if (codeset != NULL)
free(codeset);
#define verbose 1
if (verbose > 0 && charset != NULL) {
error(_("Setting input-charset to '%s' from locale.\n"),
charset);
}
}
setcharset:
/*
* Allow to switch off locale with -input-charset "".
*/
if (charset != NULL && *charset == '\0')
charset = NULL;
#endif
return charset;
}

View file

@ -0,0 +1,63 @@
/* @(#)libscgcmd.h 1.1 08/10/26 Copyright 1986-2008 J. Schilling */
#ifndef _LIBSCGCMD_H
#define _LIBSCGCMD_H
/*
* buffer.c
*/
extern int read_buffer __PR((SCSI *scgp, caddr_t bp, int cnt, int mode));
extern int write_buffer __PR((SCSI *scgp, char *buffer, long length, int mode, int bufferid, long offset));
/*
* inquiry.c
*/
extern int inquiry __PR((SCSI *scgp, caddr_t, int));
/*
* modes.c
*/
extern BOOL get_mode_params __PR((SCSI *scgp, int page, char *pagename,
Uchar *modep, Uchar *cmodep,
Uchar *dmodep, Uchar *smodep,
int *lenp));
extern BOOL set_mode_params __PR((SCSI *scgp, char *pagename, Uchar *modep,
int len, int save, int secsize));
/*
* modesense.c
*/
extern BOOL __is_atapi __PR((void));
extern BOOL allow_atapi __PR((SCSI *scgp, BOOL new));
extern int mode_select __PR((SCSI *scgp, Uchar *, int, int, int));
extern int mode_sense __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
extern int mode_select_sg0 __PR((SCSI *scgp, Uchar *, int, int, int));
extern int mode_sense_sg0 __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
extern int mode_select_g0 __PR((SCSI *scgp, Uchar *, int, int, int));
extern int mode_select_g1 __PR((SCSI *scgp, Uchar *, int, int, int));
extern int mode_sense_g0 __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
extern int mode_sense_g1 __PR((SCSI *scgp, Uchar *dp, int cnt, int page, int pcf));
/*
* read.c
*/
extern int read_scsi __PR((SCSI *scgp, caddr_t, long, int));
extern int read_g0 __PR((SCSI *scgp, caddr_t, long, int));
extern int read_g1 __PR((SCSI *scgp, caddr_t, long, int));
/*
* readcap.c
*/
extern int read_capacity __PR((SCSI *scgp));
#ifdef EOF /* stdio.h has been included */
extern void print_capacity __PR((SCSI *scgp, FILE *f));
#endif
/*
* ready.c
*/
extern BOOL unit_ready __PR((SCSI *scgp));
extern BOOL wait_unit_ready __PR((SCSI *scgp, int secs));
extern int test_unit_ready __PR((SCSI *scgp));
#endif /* _LIBSCGCMD_H */

View file

@ -29,13 +29,18 @@ static UConst char sccsid[] =
#include <schily/stdlib.h> #include <schily/stdlib.h>
#include <schily/unistd.h> #include <schily/unistd.h>
#include <schily/schily.h> #include <schily/schily.h>
#include <schily/nlsdefs.h>
#include <schily/string.h>
//#include "mkisofs.h"
#define SECTOR_SIZE (2048)
BOOL ignerr;
#include "mkisofs.h"
#include <scg/scsireg.h> #include <scg/scsireg.h>
#include <scg/scsitransp.h> #include <scg/scsitransp.h>
#include "libscgcmd.h" #include "scgcmd/libscgcmd.h"
#include "cdrdeflt.h" #include "cdrdeflt/cdrdeflt.h"
/* /*
* NOTICE: You should not make BUF_SIZE more than * NOTICE: You should not make BUF_SIZE more than
@ -48,15 +53,36 @@ static UConst char sccsid[] =
*/ */
#define BUF_SIZE (62*1024) /* Must be a multiple of 2048 */ #define BUF_SIZE (62*1024) /* Must be a multiple of 2048 */
LOCAL SCSI *scgp; enum ScsiOpenErr {
ScsiOpenErr_Ok = 0,
ScsiOpenErr_CantOpen, /*Cannot open SCSI driver*/
ScsiOpenErr_CantIO, /*Cannot get SCSI I/O buffer*/
ScsiOpenErr_Timeout,
ScsiOpenErr_Invalid
};
struct scsi_dev {
FILE *file;
SCSI *scgp;
int err;
};
LOCAL long bufsize; /* The size of the transfer buffer */ LOCAL long bufsize; /* The size of the transfer buffer */
EXPORT int readsecs __PR((UInt32_t startsecno, void *buffer, int sectorcount)); EXPORT int readsecs __PR((struct scsi_dev* src, UInt32_t startsecno, void *buffer, int sectorcount));
EXPORT int scsidev_open __PR((char *path)); EXPORT BOOL scsidev_has_error __PR((struct scsi_dev *dev));
EXPORT int scsidev_close __PR((void)); EXPORT int scsidev_error_code __PR((struct scsi_dev *dev));
EXPORT const char* scsidev_error_desc __PR((int code));
#ifdef USE_SCG
EXPORT struct scsi_dev* scsidev_open __PR((char *path));
EXPORT int scsidev_close __PR((struct scsi_dev *f));
#endif
EXPORT struct scsi_dev* scsidev_file_open __PR((const char *path));
EXPORT int EXPORT int
readsecs(startsecno, buffer, sectorcount) readsecs(src, startsecno, buffer, sectorcount)
struct scsi_dev *src;
UInt32_t startsecno; UInt32_t startsecno;
void *buffer; void *buffer;
int sectorcount; int sectorcount;
@ -69,7 +95,7 @@ readsecs(startsecno, buffer, sectorcount)
char *bp; char *bp;
long amt; long amt;
if (in_image == NULL) { if (src->file == NULL) {
/* /*
* We are using the standard CD-ROM sectorsize of 2048 bytes * We are using the standard CD-ROM sectorsize of 2048 bytes
* while the drive may be switched to 512 bytes per sector. * while the drive may be switched to 512 bytes per sector.
@ -77,7 +103,7 @@ readsecs(startsecno, buffer, sectorcount)
* XXX We assume that secsize is no more than SECTOR_SIZE * XXX We assume that secsize is no more than SECTOR_SIZE
* XXX and that SECTOR_SIZE / secsize is not a fraction. * XXX and that SECTOR_SIZE / secsize is not a fraction.
*/ */
secsize = scgp->cap->c_bsize; secsize = src->scgp->cap->c_bsize;
amount = sectorcount * SECTOR_SIZE; amount = sectorcount * SECTOR_SIZE;
secno = startsecno * (SECTOR_SIZE / secsize); secno = startsecno * (SECTOR_SIZE / secsize);
bp = buffer; bp = buffer;
@ -88,8 +114,8 @@ readsecs(startsecno, buffer, sectorcount)
amt = bufsize; amt = bufsize;
secnum = amt / secsize; secnum = amt / secsize;
if (read_scsi(scgp, bp, secno, secnum) < 0 || if (read_scsi(src->scgp, bp, secno, secnum) < 0 ||
scg_getresid(scgp) != 0) { scg_getresid(src->scgp) != 0) {
#ifdef OLD #ifdef OLD
return (-1); return (-1);
#else #else
@ -104,7 +130,7 @@ readsecs(startsecno, buffer, sectorcount)
return (SECTOR_SIZE * sectorcount); return (SECTOR_SIZE * sectorcount);
} }
f = fileno(in_image); f = fileno(src->file);
if (lseek(f, (off_t)startsecno * SECTOR_SIZE, SEEK_SET) == (off_t)-1) { if (lseek(f, (off_t)startsecno * SECTOR_SIZE, SEEK_SET) == (off_t)-1) {
comerr(_("Seek error on old image\n")); comerr(_("Seek error on old image\n"));
@ -125,13 +151,61 @@ readsecs(startsecno, buffer, sectorcount)
return (sectorcount * SECTOR_SIZE); return (sectorcount * SECTOR_SIZE);
} }
EXPORT int EXPORT BOOL scsidev_has_error (src)
struct scsi_dev *src;
{
if (NULL == src || ScsiOpenErr_Ok != src->err)
return TRUE;
else
return FALSE;
}
EXPORT int scsidev_error_code (src)
struct scsi_dev *src;
{
if (NULL == src)
return ScsiOpenErr_Invalid;
else
return src->err;
}
EXPORT const char* scsidev_error_desc (code)
int code;
{
switch (code) {
case ScsiOpenErr_Timeout:
return "Timeout waiting for device";
case ScsiOpenErr_CantIO:
return "Cannot get SCSI I/O buffer";
case ScsiOpenErr_CantOpen:
return "Cannot open SCSI driver";
case ScsiOpenErr_Invalid:
return "Invalid device handle";
default:
return "";
}
}
EXPORT struct scsi_dev*
scsidev_file_open (path)
const char* path;
{
struct scsi_dev *retval;
retval = (struct scsi_dev*)malloc(sizeof(*retval));
memset(retval, 0, sizeof(*retval));
retval->file = fopen(path, "rb");
return retval;
}
EXPORT struct scsi_dev*
scsidev_open(path) scsidev_open(path)
char *path; char *path;
{ {
char errstr[80]; char errstr[80];
char *buf; /* ignored, bit OS/2 ASPI layer needs memory which */ char *buf; /* ignored, bit OS/2 ASPI layer needs memory which */
/* has been allocated by scsi_getbuf() */ /* has been allocated by scsi_getbuf() */
struct scsi_dev *retval;
/* /*
* Call scg_remote() to force loading the remote SCSI transport library * Call scg_remote() to force loading the remote SCSI transport library
@ -142,42 +216,56 @@ scsidev_open(path)
cdr_defaults(&path, NULL, NULL, NULL, NULL); cdr_defaults(&path, NULL, NULL, NULL, NULL);
/* path, debug, verboseopen */ /* path, debug, verboseopen */
scgp = scg_open(path, errstr, sizeof (errstr), 0, 0); retval = (struct scsi_dev*)malloc(sizeof(*retval));
if (scgp == 0) { memset(retval, 0, sizeof(*retval));
errmsg(_("%s%sCannot open SCSI driver.\n"), errstr, errstr[0]?". ":"");
return (-1); retval->scgp = scg_open(path, errstr, sizeof (errstr), 0, 0);
if (retval->scgp == 0) {
retval->err = ScsiOpenErr_CantOpen;
return retval;
} }
bufsize = scg_bufsize(scgp, BUF_SIZE); bufsize = scg_bufsize(retval->scgp, BUF_SIZE);
if ((buf = scg_getbuf(scgp, bufsize)) == NULL) { if ((buf = scg_getbuf(retval->scgp, bufsize)) == NULL) {
errmsg(_("Cannot get SCSI I/O buffer.\n")); retval->err = ScsiOpenErr_CantIO;
scg_close(scgp); scg_close(retval->scgp);
return (-1); retval->scgp = NULL;
return retval;
} }
bufsize = (bufsize / SECTOR_SIZE) * SECTOR_SIZE; bufsize = (bufsize / SECTOR_SIZE) * SECTOR_SIZE;
allow_atapi(scgp, TRUE); allow_atapi(retval->scgp, TRUE);
if (!wait_unit_ready(scgp, 60)) { /* Eat Unit att / Wait for drive */ if (!wait_unit_ready(retval->scgp, 60)) { /* Eat Unit att / Wait for drive */
return (-1); retval->err = ScsiOpenErr_Timeout;
return retval;
} }
scgp->silent++; retval->scgp->silent++;
read_capacity(scgp); /* Set Capacity/Sectorsize for I/O */ read_capacity(retval->scgp); /* Set Capacity/Sectorsize for I/O */
scgp->silent--; retval->scgp->silent--;
return (1); return retval;
} }
EXPORT int EXPORT int
scsidev_close() scsidev_close(struct scsi_dev *f)
{ {
if (in_image == NULL) { int retval;
return (scg_close(scgp));
} else { if (NULL == f)
return (fclose(in_image)); return 0;
retval = 0;
if (f->scgp != NULL) {
retval = scg_close(f->scgp);
} }
if (f->file != NULL) {
retval = fclose(f->file);
}
free(f);
return (retval);
} }
#endif /* USE_SCG */ #endif /* USE_SCG */

View file

@ -10,11 +10,17 @@
/* /*
* Implemented inside multi.c in case that USE_SCG has not been defined. * Implemented inside multi.c in case that USE_SCG has not been defined.
*/ */
extern int readsecs __PR((UInt32_t startsecno, void *buffer, int sectorcount)); struct scsi_dev;
extern int readsecs __PR((struct scsi_dev* src, UInt32_t startsecno, void *buffer, int sectorcount));
extern BOOL scsidev_has_error __PR((struct scsi_dev *dev));
extern int scsidev_error_code __PR((struct scsi_dev *dev));
extern const char* scsidev_error_desc __PR((int code));
#ifdef USE_SCG #ifdef USE_SCG
extern int scsidev_open __PR((char *path)); extern struct scsi_dev* scsidev_open __PR((char *path));
extern int scsidev_close __PR((void)); extern struct scsi_dev* scsidev_file_open __PR((const char *path));
extern int scsidev_close __PR((struct scsi_dev *f));
#endif #endif
#endif /* _SCSI_H */ #endif /* _SCSI_H */