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.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) {
struct iso_volume_descriptor {
char[ISODCL(1, 1)] type; /* 711 */
char[ISODCL(2, 6)] id;
char[ISODCL(7, 7)] version_;
char[ISODCL(8, 2048)] data;
}
alias iso_listing_callback = int function(void*,const(char)*,int);
int scan_iso (const(char)* filename, iso_listing_callback callback, void* user_data);
struct iso_directory_record {
byte [ISODCL(1, 1)] length; /* 711 */
char [ISODCL(2, 2)] ext_attr_length; /* 711 */
char [ISODCL(3, 10)] extent; /* 733 */
char [ISODCL(11, 18)] size; /* 733 */
char [ISODCL(19, 25)] date; /* 7 by 711 */
byte [ISODCL(26, 26)] flags;
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;
} */
private int printer(void*, const(char)* path, int is_dir) {
writef("Entry \"%s\"", path.fromStringz);
if (is_dir != 0) {
write(" (directory)");
}
write("\n");
return 0;
}
}
@ -239,6 +27,8 @@ public string iso_to_serial (string path) {
// NPJH-50465|0D506D389F2AA444|0001|G
// ULJM-05530|5A2E0CF722EF6299|0001|G
scan_iso(path.toStringz, &printer, null);
return "UCES-00356"; //Tekken Dark Resurrection
//return "NPJH-50465"; //Hatsune Miku (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')
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')
libisoinfo = static_library(meson.project_name(),
'src/isoinfo.c',
'src/scsi.c',
dependencies: [cdrdeflt_dep],
dependencies: [cdrdeflt_dep, scgcmd_dep, schily_dep, scg_dep, siconv_dep],
install: false,
)

View file

@ -119,8 +119,14 @@
#define GET_UBYTE(a) a_to_u_byte(a)
#define infile in_image
EXPORT FILE *infile = NULL;
typedef int(*iso_listing_callback)(void*,const char*,int is_dir);
enum ScanRetCode {
ScanRetCode_Ok = 100,
ScanRetCode_Disabled,
ScanRetCode_BadInput
};
EXPORT BOOL ignerr = FALSE;
LOCAL int use_rock = 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_733 __PR((unsigned char * p));
LOCAL int parse_rr __PR((unsigned char * pnt, int len,
int cont_flag));
LOCAL int parse_rr __PR((struct scsi_dev *dev, unsigned char * pnt,
int len, int cont_flag));
LOCAL void find_rr __PR((struct iso_directory_record * idr,
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,
struct iso_directory_record * idr,
char *fname,
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,
char *fname));
LOCAL void extract_file __PR((int f,
struct iso_directory_record * idr,
char *fname));
LOCAL void parse_cl_dir __PR((struct iso_directory_record *idr,
int extent));
LOCAL void parse_cl_dir __PR((struct scsi_dev *dev,
struct iso_directory_record *idr, int extent));
LOCAL BOOL parse_de __PR((struct iso_directory_record *idr));
LOCAL void parse_dir __PR((struct todo *dp,
char * rootname, int extent, int len));
LOCAL void parse_dir __PR((struct scsi_dev *dev, struct todo *dp,
char * rootname, int extent, int len,
iso_listing_callback callback, void* user_data));
LOCAL void list_locales __PR((void));
LOCAL int time_cvt __PR((unsigned char *dp, int len));
LOCAL time_t iso9660_time __PR((unsigned char *date, int *hsecp,
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
isonum_731(p)
@ -225,7 +236,8 @@ isonum_733(p)
#endif
LOCAL int
parse_rr(pnt, len, cont_flag)
parse_rr(dev, pnt, len, cont_flag)
struct scsi_dev *dev;
unsigned char *pnt;
int len;
int cont_flag;
@ -409,12 +421,12 @@ parse_rr(pnt, len, cont_flag)
unsigned char sector[2048];
#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
lseek(fileno(infile), ((off_t)(cont_extent - sector_offset)) << 11, SEEK_SET);
read(fileno(infile), sector, sizeof (sector));
#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 '/'
@ -461,14 +473,15 @@ find_rr(idr, pntp, lenp)
}
LOCAL int
dump_rr(idr)
dump_rr(dev, idr)
struct scsi_dev *dev;
struct iso_directory_record *idr;
{
int len;
unsigned char * pnt;
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",
@ -572,7 +585,8 @@ dump_stat(rootname, idr, fname, extent)
}
LOCAL void
extract(rootname, idr, fname)
extract(dev, rootname, idr, fname)
struct scsi_dev *dev;
char *rootname;
struct iso_directory_record *idr;
char *fname;
@ -682,7 +696,7 @@ static BOOL isfirst = TRUE;
return;
}
lseek(f, 0, SEEK_END);
extract_file(f, idr, fname);
extract_file(dev, f, idr, fname);
if ((idr->flags[0] & ISO_MULTIEXTENT) == 0) {
#ifdef HAVE_FCHOWN
fchown(f, fstat_buf.st_uid, fstat_buf.st_gid);
@ -720,7 +734,8 @@ setmode:
}
LOCAL void
extract_file(f, idr, fname)
extract_file(dev, f, idr, fname)
struct scsi_dev *dev;
int f;
struct iso_directory_record *idr;
char *fname;
@ -737,7 +752,7 @@ extract_file(f, idr, fname)
while (len > 0) {
tlen = (len > sizeof (buff) ? sizeof (buff) : len);
#ifdef USE_SCG
readsecs(extent - sector_offset, buff, ISO_BLOCKS(tlen));
readsecs(dev, extent - sector_offset, buff, ISO_BLOCKS(tlen));
#else
lseek(fileno(infile), ((off_t)(extent - sector_offset)) << 11, SEEK_SET);
read(fileno(infile), buff, tlen);
@ -751,7 +766,8 @@ extract_file(f, idr, fname)
LOCAL void
parse_cl_dir(idr, extent)
parse_cl_dir(dev, idr, extent)
struct scsi_dev *dev;
struct iso_directory_record *idr;
int extent;
{
@ -759,14 +775,14 @@ parse_cl_dir(idr, extent)
strlcpy(cl_name_buf, name_buf, sizeof (cl_name_buf));
#ifdef USE_SCG
readsecs(extent - sector_offset, idr, 1);
readsecs(dev, extent - sector_offset, idr, 1);
#else
lseek(fileno(infile), ((off_t)(extent - sector_offset)) << 11, SEEK_SET);
read(fileno(infile), idr, 2048);
#endif
if (parse_de(idr) && use_rock)
dump_rr(idr);
dump_rr(dev, idr);
strlcpy(name_buf, cl_name_buf, sizeof (name_buf));
}
@ -887,11 +903,14 @@ parse_de(idr)
}
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;
char *rootname;
int extent; /* Directory extent */
int len; /* Directory size */
iso_listing_callback callback;
void *user_data;
{
struct todo *td;
int i;
@ -910,7 +929,7 @@ static int nlen = 0;
while (len > 0) {
#ifdef USE_SCG
readsecs(extent - sector_offset, buffer, ISO_BLOCKS(sizeof (buffer)));
readsecs(dev, extent - sector_offset, buffer, ISO_BLOCKS(sizeof (buffer)));
#else
lseek(fileno(infile), ((off_t)(extent - sector_offset)) << 11, SEEK_SET);
read(fileno(infile), buffer, sizeof (buffer));
@ -924,7 +943,7 @@ static int nlen = 0;
break;
parse_de(idr);
if (use_rock) {
rr_flags = dump_rr(idr);
rr_flags = dump_rr(dev, idr);
if (rr_flags & RR_FLAG_CL) {
/*
@ -933,7 +952,7 @@ static int nlen = 0;
* so we get no usable file name.
*/
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)
goto cont; /* skip rr_moved */
}
@ -969,6 +988,8 @@ static int nlen = 0;
int nextent;
struct todo *tp = dp;
(*callback)(user_data, n, 1);
nextent = isonum_733((unsigned char *)idr->extent);
while (tp) {
if (tp->extent == nextent) {
@ -996,9 +1017,13 @@ static int nlen = 0;
*todo_pp = td;
todo_pp = &td->next;
}
} else if ((idr->flags[0] & 2) &&
(idr->name[0] != 0 || idr->name[0] != 1)) {
/* this is . or .. */
} else {
callback(user_data, n, 0);
if (xtract && strcmp(xtract, n) == 0) {
extract_file(STDOUT_FILENO, idr, "stdout");
extract_file(dev, STDOUT_FILENO, idr, "stdout");
}
}
if (do_f &&
@ -1035,7 +1060,7 @@ static int nlen = 0;
S_ISDIR(fstat_buf.st_mode)) {
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(rootname, idr, n);
extract(dev, rootname, idr, n);
}
size += fstat_buf.st_size;
if ((flags & ISO_MULTIEXTENT) &&
@ -1073,14 +1098,66 @@ static int nlen = 0;
}
EXPORT int
main(argc, argv)
int argc;
char *argv[];
scan_iso (filename, callback, user_data)
const char* filename;
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 ret = 0;
char *filename = NULL;
char *sdevname = NULL;
#if defined(USE_NLS)
char *dir;
#endif
@ -1120,63 +1197,7 @@ main(argc, argv)
myuid = getuid();
#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
charset = default_charset();
if (charset == NULL) {
#if (defined(__CYGWIN32__) || defined(__CYGWIN__) || defined(__DJGPP__) || defined(__MINGW32__)) && !defined(IS_CYGWIN_1)
@ -1197,38 +1218,11 @@ setcharset:
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.
*/
#ifdef USE_SCG
readsecs(16 + toc_offset, &ipd, ISO_BLOCKS(sizeof (ipd)));
readsecs(dev, 16 + toc_offset, &ipd, ISO_BLOCKS(sizeof (ipd)));
#else
lseek(fileno(infile), ((off_t)(16 + toc_offset)) <<11, SEEK_SET);
read(fileno(infile), &ipd, sizeof (ipd));
@ -1240,7 +1234,7 @@ setcharset:
c = 17;
do {
#ifdef USE_SCG
readsecs(c + toc_offset, &jpd, ISO_BLOCKS(sizeof (jpd)));
readsecs(dev, c + toc_offset, &jpd, ISO_BLOCKS(sizeof (jpd)));
#else
lseek(fileno(infile), ((off_t)(c + toc_offset)) <<11, SEEK_SET);
read(fileno(infile), &jpd, sizeof (jpd));
@ -1248,7 +1242,7 @@ setcharset:
} while (++c < 32 && GET_UBYTE(jpd.type) != ISO_VD_END);
if (GET_UBYTE(jpd.type) == ISO_VD_END) do {
#ifdef USE_SCG
readsecs(c + toc_offset, &jpd, ISO_BLOCKS(sizeof (jpd)));
readsecs(dev, c + toc_offset, &jpd, ISO_BLOCKS(sizeof (jpd)));
#else
lseek(fileno(infile), ((off_t)(c + toc_offset)) <<11, SEEK_SET);
read(fileno(infile), &jpd, sizeof (jpd));
@ -1274,12 +1268,12 @@ setcharset:
*/
extent = isonum_733((unsigned char *)idr->extent);
#ifdef USE_SCG
readsecs(extent - sector_offset, buffer, ISO_BLOCKS(sizeof (buffer)));
readsecs(dev, extent - sector_offset, buffer, ISO_BLOCKS(sizeof (buffer)));
#else
lseek(fileno(infile), ((off_t)(extent - sector_offset)) <<11, SEEK_SET);
read(fileno(infile), buffer, sizeof (buffer));
#endif
c = dump_rr((struct iso_directory_record *) buffer);
c = dump_rr(dev, (struct iso_directory_record *) buffer);
if (c == 0 ||
(c & (RR_FLAG_SP | RR_FLAG_ER)) == 0 || su_version < 1 || rr_version < 1) {
if (!debug)
@ -1324,7 +1318,7 @@ setcharset:
block++;
#ifdef USE_SCG
readsecs(block + toc_offset, &jpd, ISO_BLOCKS(sizeof (jpd)));
readsecs(dev, block + toc_offset, &jpd, ISO_BLOCKS(sizeof (jpd)));
#else
lseek(fileno(infile),
((off_t)(block + toc_offset)) <<11, SEEK_SET);
@ -1363,17 +1357,15 @@ setcharset:
if (use_joliet)
idr = (struct iso_directory_record *)jpd.root_directory_record;
parse_dir(todo_idr, "/", isonum_733((unsigned char *)idr->extent),
isonum_733((unsigned char *)idr->size));
parse_dir(dev, todo_idr, "/", isonum_733((unsigned char *)idr->extent),
isonum_733((unsigned char *)idr->size), callback, user_data);
td = todo_idr;
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);
td = td->next;
}
if (infile != NULL)
fclose(infile);
return (ret);
}
@ -1468,3 +1460,68 @@ iso9660_time(date, hsecp, longfmt)
t -= gmtoff * 15 * 60;
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/unistd.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/scsitransp.h>
#include "libscgcmd.h"
#include "cdrdeflt.h"
#include "scgcmd/libscgcmd.h"
#include "cdrdeflt/cdrdeflt.h"
/*
* 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 */
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 */
EXPORT int readsecs __PR((UInt32_t startsecno, void *buffer, int sectorcount));
EXPORT int scsidev_open __PR((char *path));
EXPORT int scsidev_close __PR((void));
EXPORT int readsecs __PR((struct scsi_dev* src, UInt32_t startsecno, void *buffer, int sectorcount));
EXPORT BOOL scsidev_has_error __PR((struct scsi_dev *dev));
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
readsecs(startsecno, buffer, sectorcount)
readsecs(src, startsecno, buffer, sectorcount)
struct scsi_dev *src;
UInt32_t startsecno;
void *buffer;
int sectorcount;
@ -69,7 +95,7 @@ readsecs(startsecno, buffer, sectorcount)
char *bp;
long amt;
if (in_image == NULL) {
if (src->file == NULL) {
/*
* We are using the standard CD-ROM sectorsize of 2048 bytes
* 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 and that SECTOR_SIZE / secsize is not a fraction.
*/
secsize = scgp->cap->c_bsize;
secsize = src->scgp->cap->c_bsize;
amount = sectorcount * SECTOR_SIZE;
secno = startsecno * (SECTOR_SIZE / secsize);
bp = buffer;
@ -88,8 +114,8 @@ readsecs(startsecno, buffer, sectorcount)
amt = bufsize;
secnum = amt / secsize;
if (read_scsi(scgp, bp, secno, secnum) < 0 ||
scg_getresid(scgp) != 0) {
if (read_scsi(src->scgp, bp, secno, secnum) < 0 ||
scg_getresid(src->scgp) != 0) {
#ifdef OLD
return (-1);
#else
@ -104,7 +130,7 @@ readsecs(startsecno, buffer, 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) {
comerr(_("Seek error on old image\n"));
@ -125,13 +151,61 @@ readsecs(startsecno, buffer, sectorcount)
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)
char *path;
{
char errstr[80];
char *buf; /* ignored, bit OS/2 ASPI layer needs memory which */
/* has been allocated by scsi_getbuf() */
struct scsi_dev *retval;
/*
* 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);
/* path, debug, verboseopen */
scgp = scg_open(path, errstr, sizeof (errstr), 0, 0);
if (scgp == 0) {
errmsg(_("%s%sCannot open SCSI driver.\n"), errstr, errstr[0]?". ":"");
return (-1);
retval = (struct scsi_dev*)malloc(sizeof(*retval));
memset(retval, 0, sizeof(*retval));
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);
if ((buf = scg_getbuf(scgp, bufsize)) == NULL) {
errmsg(_("Cannot get SCSI I/O buffer.\n"));
scg_close(scgp);
return (-1);
bufsize = scg_bufsize(retval->scgp, BUF_SIZE);
if ((buf = scg_getbuf(retval->scgp, bufsize)) == NULL) {
retval->err = ScsiOpenErr_CantIO;
scg_close(retval->scgp);
retval->scgp = NULL;
return retval;
}
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 */
return (-1);
if (!wait_unit_ready(retval->scgp, 60)) { /* Eat Unit att / Wait for drive */
retval->err = ScsiOpenErr_Timeout;
return retval;
}
scgp->silent++;
read_capacity(scgp); /* Set Capacity/Sectorsize for I/O */
scgp->silent--;
retval->scgp->silent++;
read_capacity(retval->scgp); /* Set Capacity/Sectorsize for I/O */
retval->scgp->silent--;
return (1);
return retval;
}
EXPORT int
scsidev_close()
scsidev_close(struct scsi_dev *f)
{
if (in_image == NULL) {
return (scg_close(scgp));
} else {
return (fclose(in_image));
int retval;
if (NULL == f)
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 */

View file

@ -10,11 +10,17 @@
/*
* 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
extern int scsidev_open __PR((char *path));
extern int scsidev_close __PR((void));
extern struct scsi_dev* scsidev_open __PR((char *path));
extern struct scsi_dev* scsidev_file_open __PR((const char *path));
extern int scsidev_close __PR((struct scsi_dev *f));
#endif
#endif /* _SCSI_H */