rev |
line source |
pascal@13691
|
1 #include <sys/types.h>
|
pascal@13691
|
2 #include <fcntl.h>
|
pascal@13691
|
3 #include <stdio.h>
|
pascal@17489
|
4 #include <string.h>
|
pascal@13691
|
5 #include "iso9660.h"
|
pascal@13691
|
6 #define __ROCKRIDGE
|
pascal@17489
|
7 #ifdef __AS386_16__
|
pascal@17473
|
8 #asm
|
pascal@17473
|
9 use16 86
|
pascal@17473
|
10 #endasm
|
pascal@17489
|
11 #endif
|
pascal@13691
|
12
|
pascal@13691
|
13 char *isofilename;
|
pascal@13691
|
14 unsigned long isofileofs, isofilesize;
|
pascal@13691
|
15 unsigned short isofilemod;
|
pascal@13691
|
16 int isofd;
|
pascal@13691
|
17
|
pascal@13691
|
18 #define SECTORSZ 2048
|
pascal@13691
|
19 #define SECTORBITS 11
|
pascal@13691
|
20 static char buffer[SECTORSZ];
|
pascal@13691
|
21
|
pascal@13691
|
22 static int readsector(unsigned long offset)
|
pascal@13691
|
23 {
|
pascal@13691
|
24 return (lseek(isofd, offset, SEEK_SET) != -1
|
pascal@13691
|
25 && read(isofd, buffer, SECTORSZ) == SECTORSZ);
|
pascal@13691
|
26 }
|
pascal@13691
|
27
|
pascal@13691
|
28 int isoread(char *data, unsigned size)
|
pascal@13691
|
29 {
|
pascal@13691
|
30 int get, n;
|
pascal@13691
|
31
|
pascal@13691
|
32 if (size > isofilesize)
|
pascal@13691
|
33 size = isofilesize;
|
pascal@13691
|
34 if (lseek(isofd, isofileofs, SEEK_SET) == -1)
|
pascal@13691
|
35 return -1;
|
pascal@13691
|
36 for (get = size; get; get -= n, data += n) {
|
pascal@13691
|
37 n = read(isofd,data,get);
|
pascal@13691
|
38 if (n < 0)
|
pascal@13691
|
39 return n;
|
pascal@13691
|
40 if (n == 0)
|
pascal@13691
|
41 break;
|
pascal@13691
|
42 isofileofs += n;
|
pascal@13691
|
43 isofilesize -= n;
|
pascal@13691
|
44 }
|
pascal@13691
|
45 return size - get;
|
pascal@13691
|
46 }
|
pascal@13691
|
47
|
pascal@13691
|
48 static unsigned long isodirofs, isodirsize;
|
pascal@13691
|
49 int isoreset(char *name)
|
pascal@13691
|
50 {
|
pascal@13691
|
51 if (name)
|
pascal@13691
|
52 isofd = open(name, O_RDONLY);
|
pascal@13691
|
53 if (!readsector(16UL * 2048) || strncmp(buffer+1,"CD001",5))
|
pascal@13691
|
54 return -1;
|
pascal@13691
|
55 isodirofs = * (unsigned long *) (buffer + 0x9E);
|
pascal@13691
|
56 isodirofs <<= SECTORBITS;
|
pascal@13691
|
57 isodirsize = * (unsigned long *) (buffer + 0xA6);
|
pascal@13691
|
58 return 0;
|
pascal@13691
|
59 }
|
pascal@13691
|
60
|
pascal@13691
|
61 int isoreaddir(int restart)
|
pascal@13691
|
62 {
|
pascal@13691
|
63 static unsigned long pos, dirofs, dirsize;
|
pascal@13691
|
64 static char dots[] = "..";
|
pascal@13691
|
65 int size, n;
|
pascal@13691
|
66 #ifdef __ROCKRIDGE
|
pascal@13691
|
67 char *endname;
|
pascal@13691
|
68 #endif
|
pascal@13691
|
69
|
pascal@13691
|
70 if (restart) {
|
pascal@13691
|
71 dirofs = isodirofs;
|
pascal@13691
|
72 dirsize = isodirsize;
|
pascal@13691
|
73 pos = SECTORSZ;
|
pascal@13691
|
74 }
|
pascal@17489
|
75 if (pos >= SECTORSZ || * (short *) (buffer + pos) == 0) {
|
pascal@13691
|
76 if (dirsize < SECTORSZ) return -1;
|
pascal@13691
|
77 readsector(dirofs);
|
pascal@13691
|
78 dirofs += SECTORSZ;
|
pascal@13691
|
79 dirsize -= SECTORSZ;
|
pascal@13691
|
80 pos = 0;
|
pascal@13691
|
81 }
|
pascal@13691
|
82 size = * (short *) (buffer + pos);
|
pascal@13691
|
83 if (size == 0)
|
pascal@13691
|
84 return -1;
|
pascal@13691
|
85 isofileofs = (* (unsigned long *) (buffer + pos + 2)) << SECTORBITS;
|
pascal@13691
|
86 isofilesize = * (unsigned long *) (buffer + pos + 10);
|
pascal@13691
|
87 isofilemod = (buffer[pos + 25] & 2) ? 0040755 : 0100755;
|
pascal@13691
|
88 #ifdef __ROCKRIDGE
|
pascal@13691
|
89 endname = NULL;
|
pascal@13691
|
90 n = (buffer[pos + 32] + pos + 34) & -2;
|
pascal@13691
|
91 do {
|
pascal@13691
|
92 int len = buffer[n + 2];
|
pascal@13691
|
93 switch (* (short *) (buffer + n)) {
|
pascal@13691
|
94 case 0x4D4E: // NM
|
pascal@13691
|
95 isofilename = buffer + n + 5;
|
pascal@13691
|
96 endname = buffer + n + len;
|
pascal@13691
|
97 break;
|
pascal@13691
|
98 case 0x5850: // PX
|
pascal@13691
|
99 isofilemod = * (short *) (buffer + n + 4);
|
pascal@13691
|
100 break;
|
pascal@13691
|
101 }
|
pascal@13691
|
102 n += len;
|
pascal@13691
|
103 }
|
pascal@13691
|
104 while (n + 2 < pos + size);
|
pascal@13691
|
105 if (endname)
|
pascal@13691
|
106 *endname = 0;
|
pascal@13691
|
107 else
|
pascal@13691
|
108 #endif
|
pascal@13691
|
109 {
|
pascal@13691
|
110 isofilename = buffer + pos + 33;
|
pascal@13691
|
111 switch (* (short *) (isofilename - 1)) {
|
pascal@13691
|
112 case 0x0101:
|
pascal@13691
|
113 isofilename = dots;
|
pascal@13691
|
114 break;
|
pascal@13691
|
115 case 0x0001:
|
pascal@13691
|
116 isofilename = dots + 1;
|
pascal@13691
|
117 break;
|
pascal@13691
|
118 default:
|
pascal@13691
|
119 n = isofilename[-1];
|
pascal@13691
|
120 if (* (short *) (isofilename + n - 2) == 0x313B)
|
pascal@13691
|
121 n -= 2; // remove ;1
|
pascal@13691
|
122 if (isofilename[n - 1] == '.') n--;
|
pascal@13691
|
123 isofilename[n] = 0;
|
pascal@13691
|
124 }
|
pascal@13691
|
125 }
|
pascal@13691
|
126 pos += size;
|
pascal@13691
|
127 return 0;
|
pascal@13691
|
128 }
|
pascal@13691
|
129
|
pascal@17489
|
130 #ifndef __AS386_16__
|
pascal@17489
|
131 #define cpuhaslm() (0)
|
pascal@17489
|
132 #else
|
pascal@17473
|
133 static int cpuhaslm(void)
|
pascal@17473
|
134 {
|
pascal@17473
|
135 #asm
|
pascal@17473
|
136 pushf // save flags
|
pascal@17473
|
137 // bits 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
|
pascal@17473
|
138 // flags 0 NT IOPL OF DF IF TF SF ZF 0 AF 0 PF 1 CF
|
pascal@17473
|
139 mov ax, #0x1000
|
pascal@17473
|
140 push ax
|
pascal@17473
|
141 popf // < 286 : flags[12..15] are forced 1
|
pascal@17473
|
142 pushf // = 286 : flags[12..15] are forced 0
|
pascal@17473
|
143 pop bx // > 286 : only flags[15] is forced 0
|
pascal@17473
|
144 popf // restore flags (IOPL)
|
pascal@17473
|
145 add bh, ah // test F0 and 00 cases
|
pascal@17473
|
146 cmp bh, ah
|
pascal@17473
|
147 cbw
|
pascal@17473
|
148 jbe not386 // C=8086/80186, Z=80286
|
pascal@17473
|
149 use16 386
|
pascal@17473
|
150 pushfd
|
pascal@17473
|
151 pushfd
|
pascal@17473
|
152 pop ebx
|
pascal@17473
|
153 mov ecx, ebx
|
pascal@17473
|
154 btc ebx, #21 // toggle CPUID feature bit
|
pascal@17473
|
155 push ebx
|
pascal@17473
|
156 popfd
|
pascal@17473
|
157 pushfd
|
pascal@17473
|
158 pop ebx
|
pascal@17473
|
159 popfd
|
pascal@17473
|
160 xor ebx, ecx
|
pascal@17473
|
161 bt ebx, #21 // CPUID feature bit ?
|
pascal@17473
|
162 jnc nocpuid
|
pascal@17473
|
163 mov eax, #0x80000001 // Extended Processor Info and Feature Bits
|
pascal@17473
|
164 .byte 0x0F, 0xA2 // cpuid
|
pascal@17473
|
165 xor ax, ax
|
pascal@17473
|
166 bt edx, #29 // LM feature bit ?
|
pascal@17473
|
167 adc ax, ax
|
pascal@17473
|
168 use16 86
|
pascal@17473
|
169 nocpuid:
|
pascal@17473
|
170 not386:
|
pascal@17473
|
171 #endasm
|
pascal@17473
|
172 }
|
pascal@17489
|
173 #endif
|
pascal@17473
|
174
|
pascal@13691
|
175 #define IS_DIR(x)( ((x) & ~0777) == 040000)
|
pascal@17473
|
176 int isoopen(char *filename)
|
pascal@13691
|
177 {
|
pascal@13691
|
178 int restart;
|
pascal@17473
|
179 char *name, *s, c;
|
pascal@17473
|
180 int _64bits = cpuhaslm();
|
pascal@13691
|
181
|
pascal@17473
|
182 retry32:
|
pascal@17473
|
183 name = filename;
|
pascal@13691
|
184 while (*name == '/') {
|
pascal@13691
|
185 name++;
|
pascal@13691
|
186 isoreset(NULL);
|
pascal@13691
|
187 }
|
pascal@13691
|
188 s = name;
|
pascal@13691
|
189 while (1) {
|
pascal@13691
|
190 while (*s && *s != '/') s++;
|
pascal@13691
|
191 c = *s;
|
pascal@13691
|
192 *s = 0;
|
pascal@13691
|
193 for (restart = 1; isoreaddir(restart) == 0; restart = 0) {
|
pascal@17473
|
194 char *n = name, *i = isofilename;
|
pascal@17473
|
195 if (_64bits) {
|
pascal@17473
|
196 int len = strlen(name);
|
pascal@17489
|
197 if (strncmp(name, isofilename, len)) continue;
|
pascal@17473
|
198 n = "64";
|
pascal@17473
|
199 i += len;
|
pascal@17473
|
200 }
|
pascal@17473
|
201 if (strcmp(n, i)) continue;
|
pascal@13691
|
202 if (IS_DIR(isofilemod)) {
|
pascal@13691
|
203 isodirofs = isofileofs;
|
pascal@13691
|
204 isodirsize = isofilesize;
|
pascal@13691
|
205 if (c) {
|
pascal@13691
|
206 *s++ = c;
|
pascal@13691
|
207 name = s;
|
pascal@13691
|
208 goto next;
|
pascal@13691
|
209 }
|
pascal@13691
|
210 }
|
pascal@13691
|
211 return 0;
|
pascal@13691
|
212 }
|
pascal@17473
|
213 if (_64bits) {
|
pascal@17473
|
214 _64bits = 0;
|
pascal@17473
|
215 *s = c;
|
pascal@17473
|
216 goto retry32;
|
pascal@17473
|
217 }
|
pascal@13691
|
218 return -1;
|
pascal@13691
|
219 next: ;
|
pascal@13691
|
220 }
|
pascal@13691
|
221 }
|