~ubuntu-branches/ubuntu/trusty/grub2/trusty-updates

« back to all changes in this revision

Viewing changes to grub-core/fs/jfs.c

  • Committer: Package Import Robot
  • Author(s): Colin Watson
  • Date: 2012-09-13 18:02:04 UTC
  • mfrom: (1.17.15 upstream)
  • mto: (17.6.27 experimental)
  • mto: This revision was merged to the branch mainline in revision 145.
  • Revision ID: package-import@ubuntu.com-20120913180204-mojnmocbimlom4im
Tags: upstream-2.00
ImportĀ upstreamĀ versionĀ 2.00

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
#include <grub/dl.h>
26
26
#include <grub/types.h>
27
27
#include <grub/charset.h>
 
28
#include <grub/i18n.h>
28
29
 
29
30
GRUB_MOD_LICENSE ("GPLv3+");
30
31
 
51
52
     4096 was tested.  */
52
53
  grub_uint32_t blksz;
53
54
  grub_uint16_t log2_blksz;
54
 
 
55
 
  grub_uint8_t unused[71];
56
 
  grub_uint8_t volname[11];
57
 
  grub_uint8_t unused2[32];
 
55
  grub_uint8_t unused[14];
 
56
  grub_uint32_t flags;
 
57
  grub_uint8_t unused3[61];
 
58
  char volname[11];
 
59
  grub_uint8_t unused2[24];
58
60
  grub_uint8_t uuid[16];
 
61
  char volname2[16];
59
62
};
60
63
 
61
64
struct grub_jfs_extent
155
158
  grub_uint16_t namepart[15];
156
159
} __attribute__ ((packed));
157
160
 
 
161
struct grub_jfs_time
 
162
{
 
163
  grub_int32_t sec;
 
164
  grub_int32_t nanosec;
 
165
} __attribute__ ((packed));
 
166
 
158
167
struct grub_jfs_inode
159
168
{
160
169
  grub_uint32_t stamp;
164
173
  grub_uint64_t size;
165
174
  grub_uint8_t unused2[20];
166
175
  grub_uint32_t mode;
167
 
  grub_uint8_t unused3[72];
 
176
  struct grub_jfs_time atime;
 
177
  struct grub_jfs_time ctime;
 
178
  struct grub_jfs_time mtime;
 
179
  grub_uint8_t unused3[48];
168
180
  grub_uint8_t unused4[96];
169
181
 
170
182
  union
196
208
    struct
197
209
    {
198
210
      grub_uint8_t unused[32];
199
 
      grub_uint8_t path[128];
 
211
      grub_uint8_t path[256];
200
212
    } symlink;
201
213
  } __attribute__ ((packed));
202
214
} __attribute__ ((packed));
207
219
  grub_disk_t disk;
208
220
  struct grub_jfs_inode fileset;
209
221
  struct grub_jfs_inode currinode;
 
222
  int caseins;
210
223
  int pos;
211
224
  int linknest;
 
225
  int namecomponentlen;
212
226
} __attribute__ ((packed));
213
227
 
214
228
struct grub_jfs_diropen
229
243
  struct grub_jfs_leaf_next_dirent *next_leaf;
230
244
 
231
245
  /* The filename and inode of the last read dirent.  */
232
 
  char name[255];
 
246
  /* On-disk name is at most 255 UTF-16 codepoints.
 
247
     Every UTF-16 codepoint is at most 4 UTF-8 bytes.
 
248
   */
 
249
  char name[256 * GRUB_MAX_UTF8_PER_UTF16 + 1];
233
250
  grub_uint32_t ino;
234
251
} __attribute__ ((packed));
235
252
 
244
261
grub_jfs_blkno (struct grub_jfs_data *data, struct grub_jfs_inode *inode,
245
262
                grub_uint64_t blk)
246
263
{
247
 
  auto int getblk (struct grub_jfs_treehead *treehead,
248
 
                   struct grub_jfs_tree_extent *extents);
 
264
  auto grub_int64_t getblk (struct grub_jfs_treehead *treehead,
 
265
                            struct grub_jfs_tree_extent *extents);
249
266
 
250
 
  int getblk (struct grub_jfs_treehead *treehead,
251
 
              struct grub_jfs_tree_extent *extents)
 
267
  grub_int64_t getblk (struct grub_jfs_treehead *treehead,
 
268
                       struct grub_jfs_tree_extent *extents)
252
269
    {
253
270
      int found = -1;
254
271
      int i;
260
277
              /* Read the leafnode.  */
261
278
              if (grub_le_to_cpu32 (extents[i].offset2) <= blk
262
279
                  && ((grub_le_to_cpu16 (extents[i].extent.length))
263
 
                      + (extents[i].extent.length2 << 8)
 
280
                      + (extents[i].extent.length2 << 16)
264
281
                      + grub_le_to_cpu32 (extents[i].offset2)) > blk)
265
282
                return (blk - grub_le_to_cpu32 (extents[i].offset2)
266
283
                        + grub_le_to_cpu32 (extents[i].extent.blk2));
279
296
          } tree;
280
297
 
281
298
          if (grub_disk_read (data->disk,
282
 
                              grub_le_to_cpu32 (extents[found].extent.blk2)
 
299
                              ((grub_disk_addr_t) grub_le_to_cpu32 (extents[found].extent.blk2))
283
300
                              << (grub_le_to_cpu16 (data->sblock.log2_blksz)
284
301
                                  - GRUB_DISK_SECTOR_BITS), 0,
285
302
                              sizeof (tree), (char *) &tree))
350
367
      goto fail;
351
368
    }
352
369
 
353
 
  if (grub_le_to_cpu32 (data->sblock.blksz)
354
 
      != (1U << grub_le_to_cpu16 (data->sblock.log2_blksz)))
 
370
  if (data->sblock.blksz == 0
 
371
      || grub_le_to_cpu32 (data->sblock.blksz)
 
372
      != (1U << grub_le_to_cpu16 (data->sblock.log2_blksz))
 
373
      || grub_le_to_cpu16 (data->sblock.log2_blksz) < GRUB_DISK_SECTOR_BITS)
355
374
    {
356
375
      grub_error (GRUB_ERR_BAD_FS, "not a JFS filesystem");
357
376
      goto fail;
366
385
                      sizeof (struct grub_jfs_inode), &data->fileset))
367
386
    goto fail;
368
387
 
 
388
  if (data->sblock.flags & grub_cpu_to_le32_compile_time (0x00200000))
 
389
    data->namecomponentlen = 11;
 
390
  else
 
391
    data->namecomponentlen = 13;
 
392
 
 
393
  if (data->sblock.flags & grub_cpu_to_le32_compile_time (0x40000000))
 
394
    data->caseins = 1;
 
395
  else
 
396
    data->caseins = 0;
 
397
 
369
398
  return data;
370
399
 
371
400
 fail:
390
419
  if (!((grub_le_to_cpu32 (inode->mode)
391
420
         & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR))
392
421
    {
393
 
      grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
 
422
      grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
394
423
      return 0;
395
424
    }
396
425
 
470
499
  struct grub_jfs_leaf_next_dirent *next_leaf;
471
500
  int len;
472
501
  int nextent;
473
 
  grub_uint16_t filename[255];
 
502
  grub_uint16_t filename[256];
474
503
 
475
504
  auto void addstr (grub_uint16_t *uname, int ulen);
476
505
 
478
507
  void addstr (grub_uint16_t *name, int ulen)
479
508
    {
480
509
      while (ulen--)
481
 
        filename[strpos++] = *(name++);
 
510
        filename[strpos++] = grub_le_to_cpu16 (*(name++));
482
511
    }
483
512
 
484
513
  /* The last node, read in more.  */
518
547
      return grub_jfs_getent (diro);
519
548
    }
520
549
 
521
 
  addstr (leaf->namepart, len < 11 ? len : 11);
 
550
  addstr (leaf->namepart, len < diro->data->namecomponentlen ? len
 
551
          : diro->data->namecomponentlen);
522
552
  diro->ino = grub_le_to_cpu32 (leaf->inode);
523
 
  len -= 11;
 
553
  len -= diro->data->namecomponentlen;
524
554
 
525
555
  /* Move down to the leaf level.  */
526
556
  nextent = leaf->next;
549
579
grub_jfs_read_file (struct grub_jfs_data *data,
550
580
                    void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
551
581
                                       unsigned offset, unsigned length),
552
 
                    grub_uint64_t pos, grub_size_t len, char *buf)
 
582
                    grub_off_t pos, grub_size_t len, char *buf)
553
583
{
554
 
  grub_uint64_t i;
555
 
  grub_uint64_t blockcnt;
 
584
  grub_off_t i;
 
585
  grub_off_t blockcnt;
556
586
 
557
587
  blockcnt = (len + pos + grub_le_to_cpu32 (data->sblock.blksz) - 1)
558
588
    >> grub_le_to_cpu16 (data->sblock.log2_blksz);
605
635
/* Find the file with the pathname PATH on the filesystem described by
606
636
   DATA.  */
607
637
static grub_err_t
608
 
grub_jfs_find_file (struct grub_jfs_data *data, const char *path)
 
638
grub_jfs_find_file (struct grub_jfs_data *data, const char *path,
 
639
                    grub_uint32_t start_ino)
609
640
{
610
641
  char fpath[grub_strlen (path)];
611
642
  char *name = fpath;
614
645
 
615
646
  grub_strncpy (fpath, path, grub_strlen (path) + 1);
616
647
 
617
 
  if (grub_jfs_read_inode (data, GRUB_JFS_AGGR_INODE, &data->currinode))
 
648
  if (grub_jfs_read_inode (data, start_ino, &data->currinode))
618
649
    return grub_errno;
619
650
 
620
651
  /* Skip the first slashes.  */
641
672
 
642
673
  for (;;)
643
674
    {
644
 
      if (grub_strlen (name) == 0)
 
675
      if (name[0] == 0)
645
676
        return GRUB_ERR_NONE;
646
677
 
 
678
      if (name[0] == '.' && name[1] == 0)
 
679
        {
 
680
          if (!next)
 
681
            return 0;
 
682
 
 
683
          name = next;
 
684
          next = grub_strchr (name, '/');
 
685
          while (next && *next == '/')
 
686
            {
 
687
              next[0] = '\0';
 
688
              next++;
 
689
            }
 
690
          continue;
 
691
        }
 
692
 
 
693
      if (name[0] == '.' && name[1] == '.' && name[2] == 0)
 
694
        {
 
695
          grub_uint32_t ino = grub_le_to_cpu32 (data->currinode.dir.header.idotdot);
 
696
 
 
697
          grub_jfs_closedir (diro);
 
698
          diro = 0;
 
699
 
 
700
          if (grub_jfs_read_inode (data, ino, &data->currinode))
 
701
            break;
 
702
 
 
703
          if (!next)
 
704
            return 0;
 
705
 
 
706
          name = next;
 
707
          next = grub_strchr (name, '/');
 
708
          while (next && *next == '/')
 
709
            {
 
710
              next[0] = '\0';
 
711
              next++;
 
712
            }
 
713
 
 
714
          /* Open this directory for reading dirents.  */
 
715
          diro = grub_jfs_opendir (data, &data->currinode);
 
716
          if (!diro)
 
717
            return grub_errno;
 
718
 
 
719
          continue;
 
720
        }
 
721
 
647
722
      if (grub_jfs_getent (diro) == GRUB_ERR_OUT_OF_RANGE)
648
723
        break;
649
724
 
650
725
      /* Check if the current direntry matches the current part of the
651
726
         pathname.  */
652
 
      if (!grub_strcmp (name, diro->name))
 
727
      if (data->caseins ? grub_strcasecmp (name, diro->name) == 0
 
728
          : grub_strcmp (name, diro->name) == 0)
653
729
        {
654
730
          grub_uint32_t ino = diro->ino;
655
731
          grub_uint32_t dirino = grub_le_to_cpu32 (data->currinode.inode);
674
750
 
675
751
          name = next;
676
752
          next = grub_strchr (name, '/');
677
 
          if (next)
 
753
          while (next && *next == '/')
678
754
            {
679
755
              next[0] = '\0';
680
756
              next++;
690
766
    }
691
767
 
692
768
  grub_jfs_closedir (diro);
693
 
  grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
 
769
  grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path);
694
770
  return grub_errno;
695
771
}
696
772
 
698
774
static grub_err_t
699
775
grub_jfs_lookup_symlink (struct grub_jfs_data *data, grub_uint32_t ino)
700
776
{
701
 
  grub_uint64_t size = grub_le_to_cpu64 (data->currinode.size);
 
777
  grub_size_t size = grub_le_to_cpu64 (data->currinode.size);
702
778
  char symlink[size + 1];
703
779
 
704
780
  if (++data->linknest > GRUB_JFS_MAX_SYMLNK_CNT)
705
 
    return grub_error (GRUB_ERR_SYMLINK_LOOP, "too deep nesting of symlinks");
 
781
    return grub_error (GRUB_ERR_SYMLINK_LOOP, N_("too deep nesting of symlinks"));
706
782
 
707
 
  if (size <= 128)
708
 
    grub_strncpy (symlink, (char *) (data->currinode.symlink.path), 128);
 
783
  if (size <= sizeof (data->currinode.symlink.path))
 
784
    grub_strncpy (symlink, (char *) (data->currinode.symlink.path), size);
709
785
  else if (grub_jfs_read_file (data, 0, 0, size, symlink) < 0)
710
786
    return grub_errno;
711
787
 
715
791
  if (symlink[0] == '/')
716
792
    ino = 2;
717
793
 
718
 
  /* Now load in the old inode.  */
719
 
  if (grub_jfs_read_inode (data, ino, &data->currinode))
720
 
    return grub_errno;
721
 
 
722
 
  grub_jfs_find_file (data, symlink);
723
 
  if (grub_errno)
724
 
    grub_error (grub_errno, "cannot follow symlink `%s'", symlink);
 
794
  grub_jfs_find_file (data, symlink, ino);
725
795
 
726
796
  return grub_errno;
727
797
}
741
811
  if (!data)
742
812
    goto fail;
743
813
 
744
 
  if (grub_jfs_find_file (data, path))
 
814
  if (grub_jfs_find_file (data, path, GRUB_JFS_AGGR_INODE))
745
815
    goto fail;
746
816
 
747
817
  diro = grub_jfs_opendir (data, &data->currinode);
760
830
 
761
831
      info.dir = (grub_le_to_cpu32 (inode.mode)
762
832
                  & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_DIR;
 
833
      info.mtimeset = 1;
 
834
      info.mtime = grub_le_to_cpu32 (inode.mtime.sec);
763
835
      if (hook (diro->name, &info))
764
836
        goto fail;
765
837
    }
790
862
  if (!data)
791
863
    goto fail;
792
864
 
793
 
  grub_jfs_find_file (data, name);
 
865
  grub_jfs_find_file (data, name, GRUB_JFS_AGGR_INODE);
794
866
  if (grub_errno)
795
867
    goto fail;
796
868
 
798
870
  if (! ((grub_le_to_cpu32 (data->currinode.mode)
799
871
          & GRUB_JFS_FILETYPE_MASK) == GRUB_JFS_FILETYPE_REG))
800
872
    {
801
 
      grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a regular file");
 
873
      grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file"));
802
874
      goto fail;
803
875
    }
804
876
 
876
948
  data = grub_jfs_mount (device->disk);
877
949
 
878
950
  if (data)
879
 
    *label = grub_strndup ((char *) (data->sblock.volname), 11);
 
951
    {
 
952
      if (data->sblock.volname2[0] < ' ')
 
953
        {
 
954
          char *ptr;
 
955
          ptr = data->sblock.volname + sizeof (data->sblock.volname) - 1;
 
956
          while (ptr >= data->sblock.volname && *ptr == ' ')
 
957
            ptr--;
 
958
          *label = grub_strndup (data->sblock.volname,
 
959
                                 ptr - data->sblock.volname + 1);
 
960
        }
 
961
      else
 
962
        *label = grub_strndup (data->sblock.volname2,
 
963
                               sizeof (data->sblock.volname2));
 
964
    }
880
965
  else
881
966
    *label = 0;
882
967
 
 
968
  grub_free (data);
 
969
 
883
970
  return grub_errno;
884
971
}
885
972
 
893
980
    .close = grub_jfs_close,
894
981
    .label = grub_jfs_label,
895
982
    .uuid = grub_jfs_uuid,
 
983
#ifdef GRUB_UTIL
 
984
    .reserved_first_sector = 1,
 
985
    .blocklist_install = 1,
 
986
#endif
896
987
    .next = 0
897
988
  };
898
989