aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/9660/ichar.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/9660/ichar.c')
-rw-r--r--src/cmd/9660/ichar.c206
1 files changed, 206 insertions, 0 deletions
diff --git a/src/cmd/9660/ichar.c b/src/cmd/9660/ichar.c
new file mode 100644
index 00000000..35b0c056
--- /dev/null
+++ b/src/cmd/9660/ichar.c
@@ -0,0 +1,206 @@
+#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);
+}