wok view syslinux/stuff/iso2exe/iso9660.c @ rev 17489

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