OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [before_ORP/] [uclinux/] [uClinux-2.0.x/] [fs/] [isofs/] [rock.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 *  linux/fs/isofs/rock.c
3
 *
4
 *  (C) 1992, 1993  Eric Youngdale
5
 *
6
 *  Rock Ridge Extensions to iso9660
7
 *
8
 *  Modifed by Russell King 11/02/96
9
 *      Allows ISO rock ridge extensions to work on ARM.
10
 */
11
 
12
#include <linux/stat.h>
13
#include <linux/sched.h>
14
#include <linux/iso_fs.h>
15
#include <linux/string.h>
16
#include <linux/mm.h>
17
#include <linux/malloc.h>
18
 
19
#include "rock.h"
20
 
21
/* These functions are designed to read the system areas of a directory record
22
 * and extract relevant information.  There are different functions provided
23
 * depending upon what information we need at the time.  One function fills
24
 * out an inode structure, a second one extracts a filename, a third one
25
 * returns a symbolic link name, and a fourth one returns the extent number
26
 * for the file. */
27
 
28
#define SIG(A,B) ((A << 8) | B)
29
 
30
 
31
/* This is a way of ensuring that we have something in the system
32
   use fields that is compatible with Rock Ridge */
33
#define CHECK_SP(FAIL)                          \
34
      if(rr->u.SP.magic[0] != 0xbe) FAIL;        \
35
      if(rr->u.SP.magic[1] != 0xef) FAIL;
36
 
37
/* We define a series of macros because each function must do exactly the
38
   same thing in certain places.  We use the macros to ensure that everything
39
   is done correctly */
40
 
41
#define CONTINUE_DECLS \
42
  int cont_extent = 0, cont_offset = 0, cont_size = 0;   \
43
  void * buffer = 0
44
 
45
#define CHECK_CE                                \
46
      {cont_extent = isonum_733(rr->u.CE.extent); \
47
      cont_offset = isonum_733(rr->u.CE.offset); \
48
      cont_size = isonum_733(rr->u.CE.size);}
49
 
50
#define SETUP_ROCK_RIDGE(DE,CHR,LEN)                                            \
51
  {LEN= (int)(((struct iso_directory_record *)0)->name) + DE->name_len[0];        \
52
  if(LEN & 1) LEN++;                                                            \
53
  CHR = ((unsigned char *) DE) + LEN;                                           \
54
  LEN = *((unsigned char *) DE) - LEN;}
55
 
56
#define MAYBE_CONTINUE(LABEL,DEV) \
57
  {if (buffer) kfree(buffer); \
58
  if (cont_extent){ \
59
    int block, offset, offset1; \
60
    struct buffer_head * bh; \
61
    buffer = kmalloc(cont_size,GFP_KERNEL); \
62
    if (!buffer) goto out; \
63
    block = cont_extent; \
64
    offset = cont_offset; \
65
    offset1 = 0; \
66
    if(ISOFS_BUFFER_SIZE(DEV) == 1024) {     \
67
      block <<= 1;    \
68
      if (offset >= 1024) block++; \
69
      offset &= 1023; \
70
      if(offset + cont_size >= 1024) { \
71
          bh = bread(DEV->i_dev, block++, ISOFS_BUFFER_SIZE(DEV)); \
72
          if(!bh) {printk("Unable to read continuation Rock Ridge record\n"); \
73
                     kfree(buffer); \
74
                     buffer = NULL; } else { \
75
            memcpy(buffer, bh->b_data + offset, 1024 - offset); \
76
            brelse(bh); \
77
            offset1 = 1024 - offset; \
78
            offset = 0;} \
79
      }  \
80
    };     \
81
    if(buffer) { \
82
      bh = bread(DEV->i_dev, block, ISOFS_BUFFER_SIZE(DEV)); \
83
      if(bh){       \
84
        memcpy(buffer + offset1, bh->b_data + offset, cont_size - offset1); \
85
        brelse(bh); \
86
        chr = (unsigned char *) buffer; \
87
        len = cont_size; \
88
        cont_extent = 0; \
89
        cont_size = 0; \
90
        cont_offset = 0; \
91
        goto LABEL; \
92
      };    \
93
    } \
94
    printk("Unable to read rock-ridge attributes\n");    \
95
  }}
96
 
97
/* This is the inner layer of the get filename routine, and is called
98
   for each system area and continuation record related to the file */
99
 
100
int find_rock_ridge_relocation(struct iso_directory_record * de,
101
                               struct inode * inode) {
102
  int flag;
103
  int len;
104
  int retval;
105
  unsigned char * chr;
106
  CONTINUE_DECLS;
107
  flag = 0;
108
 
109
  /* If this is a '..' then we are looking for the parent, otherwise we
110
     are looking for the child */
111
 
112
  if (de->name[0]==1 && de->name_len[0]==1) flag = 1;
113
  /* Return value if we do not find appropriate record. */
114
  retval = isonum_733 (de->extent);
115
 
116
  if (!inode->i_sb->u.isofs_sb.s_rock) return retval;
117
 
118
  SETUP_ROCK_RIDGE(de, chr, len);
119
 repeat:
120
  {
121
    int rrflag, sig;
122
    struct rock_ridge * rr;
123
 
124
    while (len > 1){ /* There may be one byte for padding somewhere */
125
      rr = (struct rock_ridge *) chr;
126
      if (rr->len == 0) goto out; /* Something got screwed up here */
127
      sig = (chr[0] << 8) + chr[1];
128
      chr += rr->len;
129
      len -= rr->len;
130
 
131
      switch(sig){
132
      case SIG('R','R'):
133
        rrflag = rr->u.RR.flags[0];
134
        if (flag && !(rrflag & RR_PL)) goto out;
135
        if (!flag && !(rrflag & RR_CL)) goto out;
136
        break;
137
      case SIG('S','P'):
138
        CHECK_SP(goto out);
139
        break;
140
      case SIG('C','L'):
141
#ifdef DEBUG
142
        printk("RR: CL\n");
143
#endif
144
        if (flag == 0) {
145
          retval = isonum_733(rr->u.CL.location);
146
          goto out;
147
        };
148
        break;
149
      case SIG('P','L'):
150
#ifdef DEBUG
151
        printk("RR: PL\n");
152
#endif
153
        if (flag != 0) {
154
          retval = isonum_733(rr->u.PL.location);
155
          goto out;
156
        };
157
        break;
158
      case SIG('C','E'):
159
        CHECK_CE; /* This tells is if there is a continuation record */
160
        break;
161
      default:
162
        break;
163
      }
164
    };
165
  };
166
  MAYBE_CONTINUE(repeat, inode);
167
  return retval;
168
 out:
169
  if(buffer) kfree(buffer);
170
  return retval;
171
}
172
 
173
int get_rock_ridge_filename(struct iso_directory_record * de,
174
                            char * retname, struct inode * inode)
175
{
176
  int len;
177
  unsigned char * chr;
178
  CONTINUE_DECLS;
179
  int retnamlen = 0, truncate=0;
180
 
181
  if (!inode->i_sb->u.isofs_sb.s_rock) return 0;
182
  *retname = 0;
183
  retnamlen = 0;
184
 
185
  SETUP_ROCK_RIDGE(de, chr, len);
186
 repeat:
187
  {
188
    struct rock_ridge * rr;
189
    int sig;
190
 
191
    while (len > 1){ /* There may be one byte for padding somewhere */
192
      rr = (struct rock_ridge *) chr;
193
      if (rr->len == 0) goto out; /* Something got screwed up here */
194
      sig = (chr[0] << 8) + chr[1];
195
      chr += rr->len;
196
      len -= rr->len;
197
 
198
      switch(sig){
199
      case SIG('R','R'):
200
        if((rr->u.RR.flags[0] & RR_NM) == 0) goto out;
201
        break;
202
      case SIG('S','P'):
203
        CHECK_SP(goto out);
204
        break;
205
      case SIG('C','E'):
206
        CHECK_CE;
207
        break;
208
      case SIG('N','M'):
209
        if (truncate) break;
210
        if (rr->u.NM.flags & ~1) {
211
          printk("Unsupported NM flag settings (%d)\n",rr->u.NM.flags);
212
          break;
213
        };
214
        if((strlen(retname) + rr->len - 5) >= 254) {
215
          truncate = 1;
216
          break;
217
        };
218
        strncat(retname, rr->u.NM.name, rr->len - 5);
219
        retnamlen += rr->len - 5;
220
        break;
221
      case SIG('R','E'):
222
#ifdef DEBUG
223
        printk("RR: RE (%x)\n", inode->i_ino);
224
#endif
225
        if (buffer) kfree(buffer);
226
        return -1;
227
      default:
228
        break;
229
      }
230
    };
231
  }
232
  MAYBE_CONTINUE(repeat,inode);
233
  return retnamlen; /* If 0, this file did not have a NM field */
234
 out:
235
  if(buffer) kfree(buffer);
236
  return 0;
237
}
238
 
239
int parse_rock_ridge_inode(struct iso_directory_record * de,
240
                           struct inode * inode){
241
  int len;
242
  unsigned char * chr;
243
  int symlink_len = 0;
244
  CONTINUE_DECLS;
245
 
246
  if (!inode->i_sb->u.isofs_sb.s_rock) return 0;
247
 
248
  SETUP_ROCK_RIDGE(de, chr, len);
249
 repeat:
250
  {
251
    int cnt, sig;
252
    struct inode * reloc;
253
    struct rock_ridge * rr;
254
    int rootflag;
255
 
256
    while (len > 1){ /* There may be one byte for padding somewhere */
257
      rr = (struct rock_ridge *) chr;
258
      if (rr->len == 0) goto out; /* Something got screwed up here */
259
      sig = (chr[0] << 8) + chr[1];
260
      chr += rr->len;
261
      len -= rr->len;
262
 
263
      switch(sig){
264
      case SIG('R','R'):
265
        if((rr->u.RR.flags[0] &
266
            (RR_PX | RR_TF | RR_SL | RR_CL)) == 0) goto out;
267
        break;
268
      case SIG('S','P'):
269
        CHECK_SP(goto out);
270
        break;
271
      case SIG('C','E'):
272
        CHECK_CE;
273
        break;
274
      case SIG('E','R'):
275
        inode->i_sb->u.isofs_sb.s_rock = 1;
276
        printk(KERN_DEBUG"ISO9660 Extensions: ");
277
        { int p;
278
          for(p=0;p<rr->u.ER.len_id;p++) printk("%c",rr->u.ER.data[p]);
279
        };
280
          printk("\n");
281
        break;
282
      case SIG('P','X'):
283
        inode->i_mode  = isonum_733(rr->u.PX.mode);
284
        inode->i_nlink = isonum_733(rr->u.PX.n_links);
285
        inode->i_uid   = isonum_733(rr->u.PX.uid);
286
        inode->i_gid   = isonum_733(rr->u.PX.gid);
287
        break;
288
      case SIG('P','N'):
289
        { int high, low;
290
          high = isonum_733(rr->u.PN.dev_high);
291
          low = isonum_733(rr->u.PN.dev_low);
292
          /*
293
           * The Rock Ridge standard specifies that if sizeof(dev_t) <= 4,
294
           * then the high field is unused, and the device number is completely
295
           * stored in the low field.  Some writers may ignore this subtlety,
296
           * and as a result we test to see if the entire device number is
297
           * stored in the low field, and use that.
298
           */
299
          if((low & ~0xff) && high == 0) {
300
            inode->i_rdev = MKDEV(low >> 8, low & 0xff);
301
          } else {
302
            inode->i_rdev = MKDEV(high, low);
303
          }
304
        };
305
        break;
306
      case SIG('T','F'):
307
      {
308
        struct stamp *times = (struct stamp *) &(rr->u.TF.__times);
309
        /* Some RRIP writers incorrectly place ctime in the TF_CREATE field.
310
           Try to handle this correctly for either case. */
311
        cnt = 0; /* Rock ridge never appears on a High Sierra disk */
312
        if(rr->u.TF.flags & TF_CREATE)
313
          inode->i_ctime = iso_date(times[cnt++].time, 0);
314
        if(rr->u.TF.flags & TF_MODIFY)
315
          inode->i_mtime = iso_date(times[cnt++].time, 0);
316
        if(rr->u.TF.flags & TF_ACCESS)
317
          inode->i_atime = iso_date(times[cnt++].time, 0);
318
        if(rr->u.TF.flags & TF_ATTRIBUTES)
319
          inode->i_ctime = iso_date(times[cnt++].time, 0);
320
        break;
321
      }
322
      case SIG('S','L'):
323
        {int slen;
324
         struct SL_component * slp;
325
         struct SL_component * oldslp;
326
         slen = rr->len - 5;
327
         slp = (struct SL_component *)&rr->u.SL.__link;
328
         inode->i_size = symlink_len;
329
         while (slen > 1){
330
           rootflag = 0;
331
           switch(slp->flags &~1){
332
           case 0:
333
             inode->i_size += slp->len;
334
             break;
335
           case 2:
336
             inode->i_size += 1;
337
             break;
338
           case 4:
339
             inode->i_size += 2;
340
             break;
341
           case 8:
342
             rootflag = 1;
343
             inode->i_size += 1;
344
             break;
345
           default:
346
             printk("Symlink component flag not implemented\n");
347
           };
348
           slen -= slp->len + 2;
349
           oldslp = slp;
350
           slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
351
 
352
           if(slen < 2) {
353
             if(    ((rr->u.SL.flags & 1) != 0)
354
                    && ((oldslp->flags & 1) == 0) ) inode->i_size += 1;
355
             break;
356
           }
357
 
358
           /*
359
            * If this component record isn't continued, then append a '/'.
360
            */
361
           if(   (!rootflag)
362
                 && ((oldslp->flags & 1) == 0) ) inode->i_size += 1;
363
         }
364
        }
365
        symlink_len = inode->i_size;
366
        break;
367
      case SIG('R','E'):
368
        printk("Attempt to read inode for relocated directory\n");
369
        goto out;
370
      case SIG('C','L'):
371
#ifdef DEBUG
372
        printk("RR CL (%x)\n",inode->i_ino);
373
#endif
374
        inode->u.isofs_i.i_first_extent = isonum_733(rr->u.CL.location) <<
375
                inode -> i_sb -> u.isofs_sb.s_log_zone_size;
376
        reloc = iget(inode->i_sb, inode->u.isofs_i.i_first_extent);
377
        inode->i_mode = reloc->i_mode;
378
        inode->i_nlink = reloc->i_nlink;
379
        inode->i_uid = reloc->i_uid;
380
        inode->i_gid = reloc->i_gid;
381
        inode->i_rdev = reloc->i_rdev;
382
        inode->i_size = reloc->i_size;
383
        inode->i_atime = reloc->i_atime;
384
        inode->i_ctime = reloc->i_ctime;
385
        inode->i_mtime = reloc->i_mtime;
386
        iput(reloc);
387
        break;
388
      default:
389
        break;
390
      }
391
    };
392
  }
393
  MAYBE_CONTINUE(repeat,inode);
394
  return 0;
395
 out:
396
  if(buffer) kfree(buffer);
397
  return 0;
398
}
399
 
400
 
401
/* Returns the name of the file that this inode is symlinked to.  This is
402
   in malloc'd memory, so it needs to be freed, once we are through with it */
403
 
404
char * get_rock_ridge_symlink(struct inode * inode)
405
{
406
  unsigned long bufsize = ISOFS_BUFFER_SIZE(inode);
407
  unsigned char bufbits = ISOFS_BUFFER_BITS(inode);
408
  struct buffer_head * bh;
409
  unsigned char * pnt;
410
  void * cpnt = NULL;
411
  char * rpnt;
412
  struct iso_directory_record * raw_inode;
413
  CONTINUE_DECLS;
414
  int block;
415
  int sig;
416
  int rootflag;
417
  int len;
418
  unsigned char * chr;
419
  struct rock_ridge * rr;
420
 
421
  if (!inode->i_sb->u.isofs_sb.s_rock)
422
    panic("Cannot have symlink with high sierra variant of iso filesystem\n");
423
 
424
  rpnt = 0;
425
 
426
  block = inode->i_ino >> bufbits;
427
  if (!(bh=bread(inode->i_dev,block, bufsize))) {
428
    printk("unable to read i-node block");
429
    return NULL;
430
  };
431
 
432
  pnt = ((unsigned char *) bh->b_data) + (inode->i_ino & (bufsize - 1));
433
 
434
  raw_inode = ((struct iso_directory_record *) pnt);
435
 
436
  if ((inode->i_ino & (bufsize - 1)) + *pnt > bufsize){
437
    int frag1, offset;
438
 
439
    offset = (inode->i_ino & (bufsize - 1));
440
    frag1 = bufsize - offset;
441
    cpnt = kmalloc(*pnt,GFP_KERNEL);
442
    if(!cpnt) return NULL;
443
    memcpy(cpnt, bh->b_data + offset, frag1);
444
    brelse(bh);
445
    if (!(bh = bread(inode->i_dev,++block, bufsize))) {
446
      kfree(cpnt);
447
      printk("unable to read i-node block");
448
      return NULL;
449
    };
450
    offset += *pnt - bufsize;
451
    memcpy((char *)cpnt+frag1, bh->b_data, offset);
452
    pnt = ((unsigned char *) cpnt);
453
    raw_inode = ((struct iso_directory_record *) pnt);
454
  };
455
 
456
  /* Now test for possible Rock Ridge extensions which will override some of
457
     these numbers in the inode structure. */
458
 
459
  SETUP_ROCK_RIDGE(raw_inode, chr, len);
460
 
461
 repeat:
462
  while (len > 1){ /* There may be one byte for padding somewhere */
463
    rr = (struct rock_ridge *) chr;
464
    if (rr->len == 0) goto out; /* Something got screwed up here */
465
    sig = (chr[0] << 8) + chr[1];
466
    chr += rr->len;
467
    len -= rr->len;
468
 
469
    switch(sig){
470
    case SIG('R','R'):
471
      if((rr->u.RR.flags[0] & RR_SL) == 0) goto out;
472
      break;
473
    case SIG('S','P'):
474
      CHECK_SP(goto out);
475
      break;
476
    case SIG('S','L'):
477
      {int slen;
478
       struct SL_component * oldslp;
479
       struct SL_component * slp;
480
       slen = rr->len - 5;
481
       slp = (struct SL_component *)&rr->u.SL.__link;
482
       while (slen > 1){
483
         if (!rpnt){
484
           rpnt = (char *) kmalloc (inode->i_size +1, GFP_KERNEL);
485
           if (!rpnt) goto out;
486
           *rpnt = 0;
487
         };
488
         rootflag = 0;
489
         switch(slp->flags &~1){
490
         case 0:
491
           strncat(rpnt,slp->text, slp->len);
492
           break;
493
         case 2:
494
           strcat(rpnt,".");
495
           break;
496
         case 4:
497
           strcat(rpnt,"..");
498
           break;
499
         case 8:
500
           rootflag = 1;
501
           strcat(rpnt,"/");
502
           break;
503
         default:
504
           printk("Symlink component flag not implemented (%d)\n",slen);
505
         };
506
         slen -= slp->len + 2;
507
         oldslp = slp;
508
         slp = (struct SL_component *) (((char *) slp) + slp->len + 2);
509
 
510
         if(slen < 2) {
511
           /*
512
            * If there is another SL record, and this component record
513
            * isn't continued, then add a slash.
514
            */
515
           if(    ((rr->u.SL.flags & 1) != 0)
516
               && ((oldslp->flags & 1) == 0) ) strcat(rpnt,"/");
517
           break;
518
         }
519
 
520
         /*
521
          * If this component record isn't continued, then append a '/'.
522
          */
523
         if(   (!rootflag)
524
            && ((oldslp->flags & 1) == 0) ) strcat(rpnt,"/");
525
 
526
       };
527
       break;
528
     case SIG('C','E'):
529
       CHECK_CE; /* This tells is if there is a continuation record */
530
       break;
531
     default:
532
       break;
533
     }
534
    };
535
  };
536
  MAYBE_CONTINUE(repeat,inode);
537
  brelse(bh);
538
 
539
  if (cpnt) {
540
    kfree(cpnt);
541
    cpnt = NULL;
542
  };
543
 
544
  return rpnt;
545
 out:
546
  if(buffer) kfree(buffer);
547
  return 0;
548
}
549
 
550
 
551
 
552
 
553
 
554
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.