#include <u.h>#include <libc.h>#include <bio.h>#include <libsec.h>#include <ctype.h> #include "iso9660.h" /* * ISO 9660 file names must be uppercase, digits, or underscore. * We use lowercase, digits, and underscore, translating lower to upper * in mkisostring, and upper to lower in isostring. * Files with uppercase letters in their names are thus nonconforming. * Conforming files also must have a basename * at most 8 letters and at most one suffix of at most 3 letters. */char*isostring(uchar *buf, int len){ char *p, *q; p = emalloc(len+1); memmove(p, buf, len); p[len] = '\0'; while(len > 0 && p[len-1] == ' ') p[--len] = '\0'; for(q=p; *q; q++) *q = tolower(*q); q = atom(p); free(p); return q;} int isisofrog(char c){ if(c >= '0' && c <= '9') return 0; if(c >= 'a' && c <= 'z') return 0; if(c == '_') return 0; return 1;} intisbadiso9660(char *s){ char *p, *q; int i; if((p = strchr(s, '.')) != nil) { if(p-s > 8) return 1; for(q=s; q<p; q++) if(isisofrog(*q)) return 1; if(strlen(p+1) > 3) return 1; for(q=p+1; *q; q++) if(isisofrog(*q)) return 1; } else { if(strlen(s) > 8) return 1; for(q=s; *q; q++) if(isisofrog(*q)) return 1; /* * we rename files of the form [FD]dddddd * so they don't interfere with us. */ if(strlen(s) == 7 && (s[0] == 'D' || s[0] == 'F')) { for(i=1; i<7; i++) if(s[i] < '0' || s[i] > '9') break; if(i == 7) return 1; } } return 0;} /* * ISO9660 name comparison * * The standard algorithm is as follows: * Take the filenames without extensions, pad the shorter with 0x20s (spaces), * and do strcmp. If they are equal, go on. * Take the extensions, pad the shorter with 0x20s (spaces), * and do strcmp. If they are equal, go on. * Compare the version numbers. * * Since Plan 9 names are not allowed to contain characters 0x00-0x1F, * the padded comparisons are equivalent to using strcmp directly. * We still need to handle the base and extension differently, * so that .foo sorts before !foo.foo. */intisocmp(const void *va, const void *vb){ int i; char s1[32], s2[32], *b1, *b2, *e1, *e2; const Direc *a, *b; a = va; b = vb; strecpy(s1, s1+sizeof s1, a->confname); b1 = s1; strecpy(s2, s2+sizeof s2, b->confname); b2 = s2; if((e1 = strchr(b1, '.')) != nil) *e1++ = '\0'; else e1 = ""; if((e2 = strchr(b2, '.')) != nil) *e2++ = '\0'; else e2 = ""; if((i = strcmp(b1, b2)) != 0) return i; return strcmp(e1, e2);} static char*mkisostring(char *isobuf, int n, char *s){ char *p, *q, *eq; eq = isobuf+n; for(p=s, q=isobuf; *p && q < eq; p++) if('a' <= *p && *p <= 'z') *q++ = *p+'A'-'a'; else *q++ = *p; while(q < eq) *q++ = ' '; return isobuf;} voidCputisopvd(Cdimg *cd, Cdinfo info){ char buf[130]; Cputc(cd, 1); /* primary volume descriptor */ Cputs(cd, "CD001", 5); /* standard identifier */ Cputc(cd, 1); /* volume descriptor version */ Cputc(cd, 0); /* unused */ assert(~info.flags & (CDplan9|CDrockridge)); /* system identifier */ strcpy(buf, ""); if(info.flags & CDplan9) strcat(buf, "plan 9 "); if(info.flags & CDrockridge) strcat(buf, "rrip "); if(info.flags & CDbootable) strcat(buf, "boot "); if(info.flags & CDconform) strcat(buf, "iso9660"); else strcat(buf, "utf8"); struprcpy(buf, buf); Cputs(cd, buf, 32); Cputs(cd, mkisostring(buf, 32, info.volumename), 32); /* volume identifier */ Crepeat(cd, 0, 8); /* unused */ Cputn(cd, 0, 4); /* volume space size */ Crepeat(cd, 0, 32); /* unused */ Cputn(cd, 1, 2); /* volume set size */ Cputn(cd, 1, 2); /* volume sequence number */ Cputn(cd, Blocksize, 2); /* logical block size */ Cputn(cd, 0, 4); /* path table size */ Cputnl(cd, 0, 4); /* location of Lpath */ Cputnl(cd, 0, 4); /* location of optional Lpath */ Cputnm(cd, 0, 4); /* location of Mpath */ Cputnm(cd, 0, 4); /* location of optional Mpath */ Cputisodir(cd, nil, DTroot, 1, Cwoffset(cd)); /* root directory */ Cputs(cd, mkisostring(buf, 128, info.volumeset), 128); /* volume set identifier */ Cputs(cd, mkisostring(buf, 128, info.publisher), 128); /* publisher identifier */ Cputs(cd, mkisostring(buf, 128, info.preparer), 128); /* data preparer identifier */ Cputs(cd, mkisostring(buf, 128, info.application), 128); /* application identifier */ Cputs(cd, "", 37); /* copyright notice */ Cputs(cd, "", 37); /* abstract */ Cputs(cd, "", 37); /* bibliographic file */ Cputdate1(cd, now); /* volume creation date */ Cputdate1(cd, now); /* volume modification date */ Cputdate1(cd, 0); /* volume expiration date */ Cputdate1(cd, 0); /* volume effective date */ Cputc(cd, 1); /* file structure version */ Cpadblock(cd);}
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <libsec.h>
#include <ctype.h>
#include "iso9660.h"
/*
* ISO 9660 file names must be uppercase, digits, or underscore.
* We use lowercase, digits, and underscore, translating lower to upper
* in mkisostring, and upper to lower in isostring.
* Files with uppercase letters in their names are thus nonconforming.
* Conforming files also must have a basename
* at most 8 letters and at most one suffix of at most 3 letters.
*/
char*
isostring(uchar *buf, int len)
{
char *p, *q;
p = emalloc(len+1);
memmove(p, buf, len);
p[len] = '\0';
while(len > 0 && p[len-1] == ' ')
p[--len] = '\0';
for(q=p; *q; q++)
*q = tolower(*q);
q = atom(p);
free(p);
return q;
}
int
isisofrog(char c)
{
if(c >= '0' && c <= '9')
return 0;
if(c >= 'a' && c <= 'z')
return 0;
if(c == '_')
return 0;
return 1;
}
int
isbadiso9660(char *s)
{
char *p, *q;
int i;
if((p = strchr(s, '.')) != nil) {
if(p-s > 8)
return 1;
for(q=s; q<p; q++)
if(isisofrog(*q))
return 1;
if(strlen(p+1) > 3)
return 1;
for(q=p+1; *q; q++)
if(isisofrog(*q))
return 1;
} else {
if(strlen(s) > 8)
return 1;
for(q=s; *q; q++)
if(isisofrog(*q))
return 1;
/*
* we rename files of the form [FD]dddddd
* so they don't interfere with us.
*/
if(strlen(s) == 7 && (s[0] == 'D' || s[0] == 'F')) {
for(i=1; i<7; i++)
if(s[i] < '0' || s[i] > '9')
break;
if(i == 7)
return 1;
}
}
return 0;
}
/*
* ISO9660 name comparison
*
* The standard algorithm is as follows:
* Take the filenames without extensions, pad the shorter with 0x20s (spaces),
* and do strcmp. If they are equal, go on.
* Take the extensions, pad the shorter with 0x20s (spaces),
* and do strcmp. If they are equal, go on.
* Compare the version numbers.
*
* Since Plan 9 names are not allowed to contain characters 0x00-0x1F,
* the padded comparisons are equivalent to using strcmp directly.
* We still need to handle the base and extension differently,
* so that .foo sorts before !foo.foo.
*/
int
isocmp(const void *va, const void *vb)
{
int i;
char s1[32], s2[32], *b1, *b2, *e1, *e2;
const Direc *a, *b;
a = va;
b = vb;
strecpy(s1, s1+sizeof s1, a->confname);
b1 = s1;
strecpy(s2, s2+sizeof s2, b->confname);
b2 = s2;
if((e1 = strchr(b1, '.')) != nil)
*e1++ = '\0';
else
e1 = "";
if((e2 = strchr(b2, '.')) != nil)
*e2++ = '\0';
else
e2 = "";
if((i = strcmp(b1, b2)) != 0)
return i;
return strcmp(e1, e2);
}
static char*
mkisostring(char *isobuf, int n, char *s)
{
char *p, *q, *eq;
eq = isobuf+n;
for(p=s, q=isobuf; *p && q < eq; p++)
if('a' <= *p && *p <= 'z')
*q++ = *p+'A'-'a';
else
*q++ = *p;
while(q < eq)
*q++ = ' ';
return isobuf;
}
void
Cputisopvd(Cdimg *cd, Cdinfo info)
{
char buf[130];
Cputc(cd, 1); /* primary volume descriptor */
Cputs(cd, "CD001", 5); /* standard identifier */
Cputc(cd, 1); /* volume descriptor version */
Cputc(cd, 0); /* unused */
assert(~info.flags & (CDplan9|CDrockridge));
/* system identifier */
strcpy(buf, "");
if(info.flags & CDplan9)
strcat(buf, "plan 9 ");
if(info.flags & CDrockridge)
strcat(buf, "rrip ");
if(info.flags & CDbootable)
strcat(buf, "boot ");
if(info.flags & CDconform)
strcat(buf, "iso9660");
else
strcat(buf, "utf8");
struprcpy(buf, buf);
Cputs(cd, buf, 32);
Cputs(cd, mkisostring(buf, 32, info.volumename), 32); /* volume identifier */
Crepeat(cd, 0, 8); /* unused */
Cputn(cd, 0, 4); /* volume space size */
Crepeat(cd, 0, 32); /* unused */
Cputn(cd, 1, 2); /* volume set size */
Cputn(cd, 1, 2); /* volume sequence number */
Cputn(cd, Blocksize, 2); /* logical block size */
Cputn(cd, 0, 4); /* path table size */
Cputnl(cd, 0, 4); /* location of Lpath */
Cputnl(cd, 0, 4); /* location of optional Lpath */
Cputnm(cd, 0, 4); /* location of Mpath */
Cputnm(cd, 0, 4); /* location of optional Mpath */
Cputisodir(cd, nil, DTroot, 1, Cwoffset(cd)); /* root directory */
Cputs(cd, mkisostring(buf, 128, info.volumeset), 128); /* volume set identifier */
Cputs(cd, mkisostring(buf, 128, info.publisher), 128); /* publisher identifier */
Cputs(cd, mkisostring(buf, 128, info.preparer), 128); /* data preparer identifier */
Cputs(cd, mkisostring(buf, 128, info.application), 128); /* application identifier */
Cputs(cd, "", 37); /* copyright notice */
Cputs(cd, "", 37); /* abstract */
Cputs(cd, "", 37); /* bibliographic file */
Cputdate1(cd, now); /* volume creation date */
Cputdate1(cd, now); /* volume modification date */
Cputdate1(cd, 0); /* volume expiration date */
Cputdate1(cd, 0); /* volume effective date */
Cputc(cd, 1); /* file structure version */
Cpadblock(cd);
}