ichar.c (4831B)
1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <libsec.h> 5 #include <ctype.h> 6 7 #include "iso9660.h" 8 9 /* 10 * ISO 9660 file names must be uppercase, digits, or underscore. 11 * We use lowercase, digits, and underscore, translating lower to upper 12 * in mkisostring, and upper to lower in isostring. 13 * Files with uppercase letters in their names are thus nonconforming. 14 * Conforming files also must have a basename 15 * at most 8 letters and at most one suffix of at most 3 letters. 16 */ 17 char* 18 isostring(uchar *buf, int len) 19 { 20 char *p, *q; 21 22 p = emalloc(len+1); 23 memmove(p, buf, len); 24 p[len] = '\0'; 25 while(len > 0 && p[len-1] == ' ') 26 p[--len] = '\0'; 27 for(q=p; *q; q++) 28 *q = tolower((uchar)*q); 29 q = atom(p); 30 free(p); 31 return q; 32 } 33 34 int 35 isisofrog(char c) 36 { 37 if(c >= '0' && c <= '9') 38 return 0; 39 if(c >= 'a' && c <= 'z') 40 return 0; 41 if(c == '_') 42 return 0; 43 44 return 1; 45 } 46 47 int 48 isbadiso9660(char *s) 49 { 50 char *p, *q; 51 int i; 52 53 if((p = strchr(s, '.')) != nil) { 54 if(p-s > 8) 55 return 1; 56 for(q=s; q<p; q++) 57 if(isisofrog(*q)) 58 return 1; 59 if(strlen(p+1) > 3) 60 return 1; 61 for(q=p+1; *q; q++) 62 if(isisofrog(*q)) 63 return 1; 64 } else { 65 if(strlen(s) > 8) 66 return 1; 67 for(q=s; *q; q++) 68 if(isisofrog(*q)) 69 return 1; 70 71 /* 72 * we rename files of the form [FD]dddddd 73 * so they don't interfere with us. 74 */ 75 if(strlen(s) == 7 && (s[0] == 'D' || s[0] == 'F')) { 76 for(i=1; i<7; i++) 77 if(s[i] < '0' || s[i] > '9') 78 break; 79 if(i == 7) 80 return 1; 81 } 82 } 83 return 0; 84 } 85 86 /* 87 * ISO9660 name comparison 88 * 89 * The standard algorithm is as follows: 90 * Take the filenames without extensions, pad the shorter with 0x20s (spaces), 91 * and do strcmp. If they are equal, go on. 92 * Take the extensions, pad the shorter with 0x20s (spaces), 93 * and do strcmp. If they are equal, go on. 94 * Compare the version numbers. 95 * 96 * Since Plan 9 names are not allowed to contain characters 0x00-0x1F, 97 * the padded comparisons are equivalent to using strcmp directly. 98 * We still need to handle the base and extension differently, 99 * so that .foo sorts before !foo.foo. 100 */ 101 int 102 isocmp(const void *va, const void *vb) 103 { 104 int i; 105 char s1[32], s2[32], *b1, *b2, *e1, *e2; 106 const Direc *a, *b; 107 108 a = va; 109 b = vb; 110 111 strecpy(s1, s1+sizeof s1, a->confname); 112 b1 = s1; 113 strecpy(s2, s2+sizeof s2, b->confname); 114 b2 = s2; 115 if((e1 = strchr(b1, '.')) != nil) 116 *e1++ = '\0'; 117 else 118 e1 = ""; 119 if((e2 = strchr(b2, '.')) != nil) 120 *e2++ = '\0'; 121 else 122 e2 = ""; 123 124 if((i = strcmp(b1, b2)) != 0) 125 return i; 126 127 return strcmp(e1, e2); 128 } 129 130 static char* 131 mkisostring(char *isobuf, int n, char *s) 132 { 133 char *p, *q, *eq; 134 135 eq = isobuf+n; 136 for(p=s, q=isobuf; *p && q < eq; p++) 137 if('a' <= *p && *p <= 'z') 138 *q++ = *p+'A'-'a'; 139 else 140 *q++ = *p; 141 142 while(q < eq) 143 *q++ = ' '; 144 145 return isobuf; 146 } 147 148 void 149 Cputisopvd(Cdimg *cd, Cdinfo info) 150 { 151 char buf[130]; 152 153 Cputc(cd, 1); /* primary volume descriptor */ 154 Cputs(cd, "CD001", 5); /* standard identifier */ 155 Cputc(cd, 1); /* volume descriptor version */ 156 Cputc(cd, 0); /* unused */ 157 158 assert(~info.flags & (CDplan9|CDrockridge)); 159 160 /* system identifier */ 161 strcpy(buf, ""); 162 if(info.flags & CDplan9) 163 strcat(buf, "plan 9 "); 164 if(info.flags & CDrockridge) 165 strcat(buf, "rrip "); 166 if(info.flags & CDbootable) 167 strcat(buf, "boot "); 168 if(info.flags & CDconform) 169 strcat(buf, "iso9660"); 170 else 171 strcat(buf, "utf8"); 172 173 struprcpy(buf, buf); 174 Cputs(cd, buf, 32); 175 176 Cputs(cd, mkisostring(buf, 32, info.volumename), 32); /* volume identifier */ 177 178 Crepeat(cd, 0, 8); /* unused */ 179 Cputn(cd, 0, 4); /* volume space size */ 180 Crepeat(cd, 0, 32); /* unused */ 181 Cputn(cd, 1, 2); /* volume set size */ 182 Cputn(cd, 1, 2); /* volume sequence number */ 183 Cputn(cd, Blocksize, 2); /* logical block size */ 184 Cputn(cd, 0, 4); /* path table size */ 185 Cputnl(cd, 0, 4); /* location of Lpath */ 186 Cputnl(cd, 0, 4); /* location of optional Lpath */ 187 Cputnm(cd, 0, 4); /* location of Mpath */ 188 Cputnm(cd, 0, 4); /* location of optional Mpath */ 189 Cputisodir(cd, nil, DTroot, 1, Cwoffset(cd)); /* root directory */ 190 191 Cputs(cd, mkisostring(buf, 128, info.volumeset), 128); /* volume set identifier */ 192 Cputs(cd, mkisostring(buf, 128, info.publisher), 128); /* publisher identifier */ 193 Cputs(cd, mkisostring(buf, 128, info.preparer), 128); /* data preparer identifier */ 194 Cputs(cd, mkisostring(buf, 128, info.application), 128); /* application identifier */ 195 196 Cputs(cd, "", 37); /* copyright notice */ 197 Cputs(cd, "", 37); /* abstract */ 198 Cputs(cd, "", 37); /* bibliographic file */ 199 Cputdate1(cd, now); /* volume creation date */ 200 Cputdate1(cd, now); /* volume modification date */ 201 Cputdate1(cd, 0); /* volume expiration date */ 202 Cputdate1(cd, 0); /* volume effective date */ 203 Cputc(cd, 1); /* file structure version */ 204 Cpadblock(cd); 205 }