1
/* ISO9660 (CDROM) Interface for SILO filesystem access routines
3
Copyright (C) 1999 Jakub Jelinek
4
1992,1993 Eric Youngdale
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
23
#include <sys/types.h>
25
#include <linux/iso_fs.h>
28
#include <stringops.h>
32
typedef ext2_filsys isofs_filsys;
40
static struct isofs_inode inode, root_inode;
41
static int link_count = 0;
44
static int isofs_lookup (isofs_filsys, struct isofs_inode *,
45
const char *, int, struct isofs_inode *);
46
static int open_namei(isofs_filsys, const char *, struct isofs_inode *,
47
struct isofs_inode *);
49
static int ino_size_isofs (void)
54
static int ls_isofs (void)
57
return isofs_lookup (fs, &inode, "", 0, NULL);
60
static int isonum_731 (char * p)
63
| ((p[1] & 0xff) << 8)
64
| ((p[2] & 0xff) << 16)
65
| ((p[3] & 0xff) << 24));
68
#define isonum_733(p) isonum_731(p)
70
static int isofs_read_super(io_channel io)
73
struct iso_primary_descriptor iso;
75
for (i = 16; i < 100; i++) {
76
if (io_channel_read_blk (io, i, -2048, (char *)&iso))
78
if (!strncmp (iso.id, ISO_STANDARD_ID, sizeof (iso.id)))
85
root_inode.extent = isonum_733 (((struct iso_directory_record *)
86
(iso.root_directory_record))->extent);
87
root_inode.size = isonum_733 (((struct iso_directory_record *)
88
(iso.root_directory_record))->size);
93
static int open_isofs (char *device)
95
fs = (isofs_filsys) malloc (sizeof (struct struct_ext2_filsys));
99
if (((struct struct_io_manager *)(silo_io_manager))->open (device, 0, &fs->io))
102
io_channel_set_blksize (fs->io, 2048);
104
if (isofs_read_super(fs->io))
110
static int iso_date(char * p, int flag)
112
int year, month, day, hour, minute, second, tz;
121
if (flag == 0) tz = p[6]; /* High sierra has no time zone */
127
int monlen[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
131
days += (year+1) / 4;
132
for (i = 1; i < month; i++)
134
if (((year+2) % 4) == 0 && month > 2)
137
crtime = ((((days * 24) + hour) * 60 + minute) * 60)
144
if (-52 <= tz && tz <= 52)
145
crtime -= tz * 15 * 60;
151
static void parse_rr (isofs_filsys fs, unsigned char *chr, unsigned char *end,
152
char *name, char *symlink, struct silo_inode *sino)
154
int cont_extent = 0, cont_offset = 0, cont_size = 0;
155
struct rock_ridge *rr;
164
rr = (struct rock_ridge *) chr;
165
if (rr->len == 0) goto out;
166
sig = (chr[0] << 8) + chr[1];
171
if((rr->u.RR.flags[0] &
172
(RR_PX | RR_TF | RR_SL | RR_CL | RR_NM | RR_PX | RR_TF)) == 0)
177
if (rr->u.NM.flags & 6) break;
178
if (rr->u.NM.flags & ~1) {
179
printf ("Unsupported NM flag settings (%d)\n",rr->u.NM.flags);
182
if((strlen(name) + rr->len - 5) >= 254) {
186
strncat(name, rr->u.NM.name, rr->len - 5);
191
struct SL_component * slp;
192
struct SL_component * oldslp;
194
slp = &rr->u.SL.link;
195
sino->size = symlink_len;
199
switch(slp->flags &~1) {
201
sino->size += slp->len;
202
strncat (symlink, slp->text, slp->len);
206
strcat (symlink, ".");
210
strcat (symlink, "..");
215
strcat (symlink, "/");
218
printf("Symlink component flag not implemented\n");
220
slen -= slp->len + 2;
222
slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
225
if(((rr->u.SL.flags & 1) != 0)
226
&& ((oldslp->flags & 1) == 0) ) sino->size += 1;
231
* If this component record isn't continued, then append a '/'.
233
if (!rootflag && (oldslp->flags & 1) == 0) {
234
strcat (symlink, "/");
240
symlink_len = sino->size;
246
sino->mode = isonum_733(rr->u.PX.mode);
247
sino->uid = isonum_733(rr->u.PX.uid);
248
sino->gid = isonum_733(rr->u.PX.gid);
252
if(rr->u.TF.flags & TF_CREATE)
254
if(rr->u.TF.flags & TF_MODIFY)
255
sino->mtime = iso_date(rr->u.TF.times[cnt++].time, 0);
258
if (chr >= end && cont_extent) {
259
char *sect = alloca (2048);
260
if (io_channel_read_blk (fs->io, cont_extent, 1, sect))
262
parse_rr (fs, (unsigned char *)(§[cont_offset]),
263
(unsigned char *)(§[cont_offset + cont_size - 3]),
264
name, symlink, sino);
271
static int isofs_lookup (isofs_filsys fs, struct isofs_inode *dir,
272
const char *name, int len, struct isofs_inode *result)
278
struct iso_directory_record *idr;
280
struct silo_inode sino;
286
if (io_channel_read_blk (fs->io, block, 1, buffer)) {
287
printf ("Could not read directory\n");
295
idr = (struct iso_directory_record *) (buffer + i);
299
i += (unsigned char)idr->length[0];
300
strncpy(namebuf, idr->name, (unsigned char)idr->name_len[0]);
301
namebuf[(unsigned char)idr->name_len[0]] = 0;
303
rr = (unsigned char *)(idr + 1);
304
rr += ((unsigned char)idr->name_len[0]) - sizeof(idr->name);
306
if (!(idr->name_len[0] & 1))
310
memset(&sino, 0, sizeof(struct silo_inode));
311
parse_rr (fs, rr, (unsigned char *)(&buffer[i-3]), namebuf, symlink, &sino);
313
if (idr->name_len[0] == 1 && !idr->name[0])
314
strcpy(namebuf, ".");
315
else if (idr->name_len[0] == 1 && idr->name[0] == 1)
316
strcpy(namebuf, "..");
318
if (result == NULL) {
319
/* We aren't returning a result inode, so we must be
321
register_silo_inode(sino.mtime, sino.size?:isonum_733(idr->size),
322
sino.mode, sino.uid, sino.gid, namebuf,
323
*symlink ? symlink : NULL);
324
} else if ((!len && namebuf[0] == '.' && !namebuf[1]) ||
325
(strlen(namebuf) == len && !memcmp(namebuf, name, len))) {
328
if (link_count > 5) {
329
printf ("Symlink loop, stopping.\n");
330
return -1; /* Loop */
333
error = open_namei (fs, symlink, result, dir);
337
result->extent = isonum_733 (idr->extent);
338
result->size = isonum_733 (idr->size);
342
if (i >= 2048 - sizeof(struct iso_directory_record) + sizeof(idr->name))
352
static int dir_namei(isofs_filsys fs, const char *pathname, int *namelen,
353
const char **name, struct isofs_inode *base,
354
struct isofs_inode *res_inode)
357
const char *thisname;
359
struct isofs_inode inode;
361
if ((c = *pathname) == '/') {
367
for(len=0;(c = *(pathname++))&&(c != '/');len++);
369
if (isofs_lookup (fs, base, thisname, len, &inode)) return -1;
378
static int open_namei(isofs_filsys fs, const char *pathname,
379
struct isofs_inode *res_inode,
380
struct isofs_inode *base)
382
const char *basename;
384
struct isofs_inode dir, inode;
386
if (dir_namei(fs, pathname, &namelen, &basename, base, &dir)) return -1;
387
if (!namelen) { /* special case: '/usr/' etc */
391
if (isofs_lookup (fs, &dir, basename, namelen, &inode)) return -1;
396
struct fs_ops iso_fs_ops;
398
static int isofs_namei (const char *filename)
403
ret = open_namei (fs, filename, &inode, &root_inode);
404
iso_fs_ops.have_inode = (ret) ? 0 : 1;
409
static void isofs_close(void)
415
static int isofs_block_iterate(void)
422
size = (inode.size + 2047) / 2048;
423
for (i = 0; i < size; i++, nr++) {
424
switch (dump_block (&nr, i)) {
430
return dump_finish();
433
static void print_error_isofs (int error_val) {
434
printf("Unknown isofs error");
437
struct fs_ops iso_fs_ops = {
438
name: "ISO-9660 CDROM",
441
dump: isofs_block_iterate,
443
ino_size: ino_size_isofs,
444
print_error: print_error_isofs,
445
namei_follow: isofs_namei,