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

« back to all changes in this revision

Viewing changes to grub-core/fs/hfs.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:
28
28
#include <grub/dl.h>
29
29
#include <grub/types.h>
30
30
#include <grub/hfs.h>
 
31
#include <grub/i18n.h>
31
32
 
32
33
GRUB_MOD_LICENSE ("GPLv3+");
33
34
 
133
134
  grub_uint8_t type;
134
135
  grub_uint8_t unused[5];
135
136
  grub_uint32_t dirid;
 
137
  grub_uint32_t ctime;
 
138
  grub_uint32_t mtime;
136
139
} __attribute__ ((packed));
137
140
 
138
141
/* Information about a file.  */
144
147
  grub_uint32_t fileid;
145
148
  grub_uint8_t unused2[2];
146
149
  grub_uint32_t size;
147
 
  grub_uint8_t unused3[44];
 
150
  grub_uint8_t unused3[18];
 
151
  grub_uint32_t mtime;
 
152
  grub_uint8_t unused4[22];
148
153
 
149
154
  /* The first 3 extents of the file.  The other extents can be found
150
155
     in the extent overflow file.  */
240
245
grub_hfs_read_file (struct grub_hfs_data *data,
241
246
                    void NESTED_FUNC_ATTR (*read_hook) (grub_disk_addr_t sector,
242
247
                                       unsigned offset, unsigned length),
243
 
                     int pos, grub_size_t len, char *buf)
 
248
                    grub_off_t pos, grub_size_t len, char *buf)
244
249
{
245
 
  int i;
246
 
  int blockcnt;
247
 
 
248
 
  blockcnt = ((len + pos)
249
 
              + data->blksz - 1) / data->blksz;
250
 
 
251
 
  for (i = pos / data->blksz; i < blockcnt; i++)
 
250
  grub_off_t i;
 
251
  grub_off_t blockcnt;
 
252
 
 
253
  blockcnt = grub_divmod64 (((len + pos)
 
254
                             + data->blksz - 1), data->blksz, 0);
 
255
 
 
256
  for (i = grub_divmod64 (pos, data->blksz, 0); i < blockcnt; i++)
252
257
    {
253
 
      int blknr;
254
 
      int blockoff = pos % data->blksz;
255
 
      int blockend = data->blksz;
 
258
      grub_disk_addr_t blknr;
 
259
      grub_off_t blockoff;
 
260
      grub_off_t blockend = data->blksz;
256
261
 
257
262
      int skipfirst = 0;
258
263
 
 
264
      grub_divmod64 (pos, data->blksz, &blockoff);
 
265
 
259
266
      blknr = grub_hfs_block (data, data->extents, data->fileid, i, 1);
260
267
      if (grub_errno)
261
268
        return -1;
263
270
      /* Last block.  */
264
271
      if (i == blockcnt - 1)
265
272
        {
266
 
          blockend = (len + pos) % data->blksz;
 
273
          grub_divmod64 ((len + pos), data->blksz, &blockend);
267
274
 
268
275
          /* The last portion is exactly EXT2_BLOCK_SIZE (data).  */
269
276
          if (! blockend)
271
278
        }
272
279
 
273
280
      /* First block.  */
274
 
      if (i == pos / data->blksz)
 
281
      if (i == grub_divmod64 (pos, data->blksz, 0))
275
282
        {
276
283
          skipfirst = blockoff;
277
284
          blockend -= skipfirst;
321
328
    goto fail;
322
329
 
323
330
  /* Check if this is a HFS filesystem.  */
324
 
  if (grub_be_to_cpu16 (data->sblock.magic) != GRUB_HFS_MAGIC)
 
331
  if (grub_be_to_cpu16 (data->sblock.magic) != GRUB_HFS_MAGIC
 
332
      || (data->sblock.blksz & grub_cpu_to_be32_compile_time (0xc00001ff)))
325
333
    {
326
334
      grub_error (GRUB_ERR_BAD_FS, "not an HFS filesystem");
327
335
      goto fail;
744
752
         entry.  In case of a non-leaf mode it will be used to lookup
745
753
         the rest of the tree.  */
746
754
      if (cmp <= 0)
747
 
        {
748
 
          grub_uint32_t *node = (grub_uint32_t *) rec->data;
749
 
          found = grub_be_to_cpu32 (*node);
750
 
        }
 
755
        found = grub_be_to_cpu32 (grub_get_unaligned32 (rec->data));
751
756
      else /* The key can not be found in the tree. */
752
757
        return 1;
753
758
 
811
816
      struct grub_hfs_catalog_key *ckey = rec->key;
812
817
 
813
818
      if (grub_hfs_cmp_catkeys (rec->key, (void *) &key) <= 0)
814
 
        found = grub_be_to_cpu32 (*(grub_uint32_t *) rec->data);
 
819
        found = grub_be_to_cpu32 (grub_get_unaligned32 (rec->data));
815
820
 
816
821
      if (hnd->type == 0xFF && ckey->strlen > 0)
817
822
        {
859
864
  return grub_errno;
860
865
}
861
866
 
 
867
#define MAX_UTF8_PER_MAC_ROMAN 3
 
868
 
 
869
static const char macroman[0x80][MAX_UTF8_PER_MAC_ROMAN + 1] =
 
870
  {
 
871
    /* 80 */ "\xc3\x84",
 
872
    /* 81 */ "\xc3\x85",
 
873
    /* 82 */ "\xc3\x87",
 
874
    /* 83 */ "\xc3\x89",
 
875
    /* 84 */ "\xc3\x91",
 
876
    /* 85 */ "\xc3\x96",
 
877
    /* 86 */ "\xc3\x9c",
 
878
    /* 87 */ "\xc3\xa1",
 
879
    /* 88 */ "\xc3\xa0",
 
880
    /* 89 */ "\xc3\xa2",
 
881
    /* 8A */ "\xc3\xa4",
 
882
    /* 8B */ "\xc3\xa3",
 
883
    /* 8C */ "\xc3\xa5",
 
884
    /* 8D */ "\xc3\xa7",
 
885
    /* 8E */ "\xc3\xa9",
 
886
    /* 8F */ "\xc3\xa8",
 
887
    /* 90 */ "\xc3\xaa",
 
888
    /* 91 */ "\xc3\xab",
 
889
    /* 92 */ "\xc3\xad",
 
890
    /* 93 */ "\xc3\xac",
 
891
    /* 94 */ "\xc3\xae",
 
892
    /* 95 */ "\xc3\xaf",
 
893
    /* 96 */ "\xc3\xb1",
 
894
    /* 97 */ "\xc3\xb3",
 
895
    /* 98 */ "\xc3\xb2",
 
896
    /* 99 */ "\xc3\xb4",
 
897
    /* 9A */ "\xc3\xb6",
 
898
    /* 9B */ "\xc3\xb5",
 
899
    /* 9C */ "\xc3\xba",
 
900
    /* 9D */ "\xc3\xb9",
 
901
    /* 9E */ "\xc3\xbb",
 
902
    /* 9F */ "\xc3\xbc",
 
903
    /* A0 */ "\xe2\x80\xa0",
 
904
    /* A1 */ "\xc2\xb0",
 
905
    /* A2 */ "\xc2\xa2",
 
906
    /* A3 */ "\xc2\xa3",
 
907
    /* A4 */ "\xc2\xa7",
 
908
    /* A5 */ "\xe2\x80\xa2",
 
909
    /* A6 */ "\xc2\xb6",
 
910
    /* A7 */ "\xc3\x9f",
 
911
    /* A8 */ "\xc2\xae",
 
912
    /* A9 */ "\xc2\xa9",
 
913
    /* AA */ "\xe2\x84\xa2",
 
914
    /* AB */ "\xc2\xb4",
 
915
    /* AC */ "\xc2\xa8",
 
916
    /* AD */ "\xe2\x89\xa0",
 
917
    /* AE */ "\xc3\x86",
 
918
    /* AF */ "\xc3\x98",
 
919
    /* B0 */ "\xe2\x88\x9e",
 
920
    /* B1 */ "\xc2\xb1",
 
921
    /* B2 */ "\xe2\x89\xa4",
 
922
    /* B3 */ "\xe2\x89\xa5",
 
923
    /* B4 */ "\xc2\xa5",
 
924
    /* B5 */ "\xc2\xb5",
 
925
    /* B6 */ "\xe2\x88\x82",
 
926
    /* B7 */ "\xe2\x88\x91",
 
927
    /* B8 */ "\xe2\x88\x8f",
 
928
    /* B9 */ "\xcf\x80",
 
929
    /* BA */ "\xe2\x88\xab",
 
930
    /* BB */ "\xc2\xaa",
 
931
    /* BC */ "\xc2\xba",
 
932
    /* BD */ "\xce\xa9",
 
933
    /* BE */ "\xc3\xa6",
 
934
    /* BF */ "\xc3\xb8",
 
935
    /* C0 */ "\xc2\xbf",
 
936
    /* C1 */ "\xc2\xa1",
 
937
    /* C2 */ "\xc2\xac",
 
938
    /* C3 */ "\xe2\x88\x9a",
 
939
    /* C4 */ "\xc6\x92",
 
940
    /* C5 */ "\xe2\x89\x88",
 
941
    /* C6 */ "\xe2\x88\x86",
 
942
    /* C7 */ "\xc2\xab",
 
943
    /* C8 */ "\xc2\xbb",
 
944
    /* C9 */ "\xe2\x80\xa6",
 
945
    /* CA */ "\xc2\xa0",
 
946
    /* CB */ "\xc3\x80",
 
947
    /* CC */ "\xc3\x83",
 
948
    /* CD */ "\xc3\x95",
 
949
    /* CE */ "\xc5\x92",
 
950
    /* CF */ "\xc5\x93",
 
951
    /* D0 */ "\xe2\x80\x93",
 
952
    /* D1 */ "\xe2\x80\x94",
 
953
    /* D2 */ "\xe2\x80\x9c",
 
954
    /* D3 */ "\xe2\x80\x9d",
 
955
    /* D4 */ "\xe2\x80\x98",
 
956
    /* D5 */ "\xe2\x80\x99",
 
957
    /* D6 */ "\xc3\xb7",
 
958
    /* D7 */ "\xe2\x97\x8a",
 
959
    /* D8 */ "\xc3\xbf",
 
960
    /* D9 */ "\xc5\xb8",
 
961
    /* DA */ "\xe2\x81\x84",
 
962
    /* DB */ "\xe2\x82\xac",
 
963
    /* DC */ "\xe2\x80\xb9",
 
964
    /* DD */ "\xe2\x80\xba",
 
965
    /* DE */ "\xef\xac\x81",
 
966
    /* DF */ "\xef\xac\x82",
 
967
    /* E0 */ "\xe2\x80\xa1",
 
968
    /* E1 */ "\xc2\xb7",
 
969
    /* E2 */ "\xe2\x80\x9a",
 
970
    /* E3 */ "\xe2\x80\x9e",
 
971
    /* E4 */ "\xe2\x80\xb0",
 
972
    /* E5 */ "\xc3\x82",
 
973
    /* E6 */ "\xc3\x8a",
 
974
    /* E7 */ "\xc3\x81",
 
975
    /* E8 */ "\xc3\x8b",
 
976
    /* E9 */ "\xc3\x88",
 
977
    /* EA */ "\xc3\x8d",
 
978
    /* EB */ "\xc3\x8e",
 
979
    /* EC */ "\xc3\x8f",
 
980
    /* ED */ "\xc3\x8c",
 
981
    /* EE */ "\xc3\x93",
 
982
    /* EF */ "\xc3\x94",
 
983
    /* F0 */ "\xef\xa3\xbf",
 
984
    /* F1 */ "\xc3\x92",
 
985
    /* F2 */ "\xc3\x9a",
 
986
    /* F3 */ "\xc3\x9b",
 
987
    /* F4 */ "\xc3\x99",
 
988
    /* F5 */ "\xc4\xb1",
 
989
    /* F6 */ "\xcb\x86",
 
990
    /* F7 */ "\xcb\x9c",
 
991
    /* F8 */ "\xc2\xaf",
 
992
    /* F9 */ "\xcb\x98",
 
993
    /* FA */ "\xcb\x99",
 
994
    /* FB */ "\xcb\x9a",
 
995
    /* FC */ "\xc2\xb8",
 
996
    /* FD */ "\xcb\x9d",
 
997
    /* FE */ "\xcb\x9b",
 
998
    /* FF */ "\xcb\x87",
 
999
  };
 
1000
 
 
1001
static void
 
1002
macroman_to_utf8 (char *to, const grub_uint8_t *from, grub_size_t len,
 
1003
                  int translate_slash)
 
1004
{
 
1005
  char *optr = to;
 
1006
  const grub_uint8_t *iptr;
 
1007
 
 
1008
  for (iptr = from; iptr < from + len && *iptr; iptr++)
 
1009
    {
 
1010
      /* Translate '/' to ':' as per HFS spec.  */
 
1011
      if (*iptr == '/' && translate_slash)
 
1012
        {
 
1013
          *optr++ = ':';
 
1014
          continue;
 
1015
        }       
 
1016
      if (!(*iptr & 0x80))
 
1017
        {
 
1018
          *optr++ = *iptr;
 
1019
          continue;
 
1020
        }
 
1021
      optr = grub_stpcpy (optr, macroman[*iptr & 0x7f]);
 
1022
    }
 
1023
  *optr = 0;
 
1024
}
 
1025
 
 
1026
static grub_ssize_t
 
1027
utf8_to_macroman (grub_uint8_t *to, const char *from)
 
1028
{
 
1029
  grub_uint8_t *end = to + 31;
 
1030
  grub_uint8_t *optr = to;
 
1031
  const char *iptr = from;
 
1032
  
 
1033
  while (*iptr && optr < end)
 
1034
    {
 
1035
      int i, clen;
 
1036
      /* Translate ':' to '/' as per HFS spec.  */
 
1037
      if (*iptr == ':')
 
1038
        {
 
1039
          *optr++ = '/';
 
1040
          iptr++;
 
1041
          continue;
 
1042
        }       
 
1043
      if (!(*iptr & 0x80))
 
1044
        {
 
1045
          *optr++ = *iptr++;
 
1046
          continue;
 
1047
        }
 
1048
      clen = 2;
 
1049
      if ((*iptr & 0xf0) == 0xe0)
 
1050
        clen++;
 
1051
      for (i = 0; i < 0x80; i++)
 
1052
        if (grub_memcmp (macroman[i], iptr, clen) == 0)
 
1053
          break;
 
1054
      if (i == 0x80)
 
1055
        break;
 
1056
      *optr++ = i | 0x80;
 
1057
      iptr += clen;
 
1058
    }
 
1059
  /* Too long or not encodable.  */
 
1060
  if (*iptr)
 
1061
    return -1;
 
1062
  return optr - to;
 
1063
}
 
1064
 
862
1065
 
863
1066
/* Find a file or directory with the pathname PATH in the filesystem
864
1067
   DATA.  Return the file record in RETDATA when it is non-zero.
879
1082
 
880
1083
  if (path[0] != '/')
881
1084
    {
882
 
      grub_error (GRUB_ERR_BAD_FILENAME, "bad filename");
 
1085
      grub_error (GRUB_ERR_BAD_FILENAME, N_("invalid file name `%s'"), path);
883
1086
      return 0;
884
1087
    }
885
1088
 
893
1096
 
894
1097
  while (path && grub_strlen (path))
895
1098
    {
 
1099
      grub_ssize_t slen;
896
1100
      if (fdrec.frec.type != GRUB_HFS_FILETYPE_DIR)
897
1101
        {
898
 
          grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
 
1102
          grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
899
1103
          goto fail;
900
1104
        }
901
1105
 
910
1114
      struct grub_hfs_catalog_key key;
911
1115
 
912
1116
      key.parent_dir = grub_cpu_to_be32 (inode);
913
 
      key.strlen = grub_strlen (path);
914
 
      grub_strcpy ((char *) (key.str), path);
 
1117
      slen = utf8_to_macroman (key.str, path);
 
1118
      if (slen < 0)
 
1119
        {
 
1120
          grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), path);
 
1121
          goto fail;
 
1122
        }
 
1123
      key.strlen = slen;
915
1124
 
916
1125
      /* Lookup this node.  */
917
1126
      if (! grub_hfs_find_node (data, (char *) &key, data->cat_root,
918
1127
                                0, (char *) &fdrec.frec, sizeof (fdrec.frec)))
919
1128
        {
920
 
          grub_error (GRUB_ERR_FILE_NOT_FOUND, "file not found");
 
1129
          grub_error (GRUB_ERR_FILE_NOT_FOUND, N_("file `%s' not found"), origpath);
921
1130
          goto fail;
922
1131
        }
923
1132
 
952
1161
 
953
1162
  int dir_hook (struct grub_hfs_record *rec)
954
1163
    {
955
 
      char fname[32] = { 0 };
956
 
      char *filetype = rec->data;
 
1164
      struct grub_hfs_dirrec *drec = rec->data;
 
1165
      struct grub_hfs_filerec *frec = rec->data;
957
1166
      struct grub_hfs_catalog_key *ckey = rec->key;
 
1167
      char fname[sizeof (ckey->str) * MAX_UTF8_PER_MAC_ROMAN + 1];
958
1168
      struct grub_dirhook_info info;
 
1169
      grub_size_t len;
 
1170
 
 
1171
      grub_memset (fname, 0, sizeof (fname));
 
1172
 
959
1173
      grub_memset (&info, 0, sizeof (info));
960
1174
 
961
 
      grub_strncpy (fname, (char *) (ckey->str), ckey->strlen);
962
 
 
963
 
      if (*filetype == GRUB_HFS_FILETYPE_DIR
964
 
          || *filetype == GRUB_HFS_FILETYPE_FILE)
965
 
        {
966
 
          info.dir = (*filetype == GRUB_HFS_FILETYPE_DIR);
967
 
          return hook (fname, &info);
968
 
        }
 
1175
      len = ckey->strlen;
 
1176
      if (len > sizeof (ckey->str))
 
1177
        len = sizeof (ckey->str);
 
1178
      macroman_to_utf8 (fname, ckey->str, len, 1);
 
1179
 
 
1180
      info.case_insensitive = 1;
 
1181
 
 
1182
      if (drec->type == GRUB_HFS_FILETYPE_DIR)
 
1183
        {
 
1184
          info.dir = 1;
 
1185
          info.mtimeset = 1;
 
1186
          info.mtime = grub_be_to_cpu32 (drec->mtime) - 2082844800;
 
1187
          return hook (fname, &info);
 
1188
        }
 
1189
      if (frec->type == GRUB_HFS_FILETYPE_FILE)
 
1190
        {
 
1191
          info.dir = 0;
 
1192
          info.mtimeset = 1;
 
1193
          info.mtime = grub_be_to_cpu32 (frec->mtime) - 2082844800;
 
1194
          return hook (fname, &info);
 
1195
        }
 
1196
 
969
1197
      return 0;
970
1198
    }
971
1199
 
984
1212
 
985
1213
  if (frec.type != GRUB_HFS_FILETYPE_DIR)
986
1214
    {
987
 
      grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a directory");
 
1215
      grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a directory"));
988
1216
      goto fail;
989
1217
    }
990
1218
 
1020
1248
  if (frec.type != GRUB_HFS_FILETYPE_FILE)
1021
1249
    {
1022
1250
      grub_free (data);
1023
 
      grub_error (GRUB_ERR_BAD_FILE_TYPE, "not a file");
 
1251
      grub_error (GRUB_ERR_BAD_FILE_TYPE, N_("not a regular file"));
1024
1252
      grub_dl_unref (my_mod);
1025
1253
      return grub_errno;
1026
1254
    }
1065
1293
  data = grub_hfs_mount (device->disk);
1066
1294
 
1067
1295
  if (data)
1068
 
    *label = grub_strndup ((char *) (data->sblock.volname + 1),
1069
 
                           *data->sblock.volname);
 
1296
    {
 
1297
      grub_size_t len = data->sblock.volname[0];
 
1298
      if (len > sizeof (data->sblock.volname) - 1)
 
1299
        len = sizeof (data->sblock.volname) - 1;
 
1300
      *label = grub_malloc (len * MAX_UTF8_PER_MAC_ROMAN + 1);
 
1301
      if (*label)
 
1302
        macroman_to_utf8 (*label, data->sblock.volname + 1,
 
1303
                          len + 1, 0);
 
1304
    }
1070
1305
  else
1071
1306
    *label = 0;
1072
1307
 
1075
1310
}
1076
1311
 
1077
1312
static grub_err_t
 
1313
grub_hfs_mtime (grub_device_t device, grub_int32_t *tm)
 
1314
{
 
1315
  struct grub_hfs_data *data;
 
1316
 
 
1317
  data = grub_hfs_mount (device->disk);
 
1318
 
 
1319
  if (data)
 
1320
    *tm = grub_be_to_cpu32 (data->sblock.mtime) - 2082844800;
 
1321
  else
 
1322
    *tm = 0;
 
1323
 
 
1324
  grub_free (data);
 
1325
  return grub_errno;
 
1326
}
 
1327
 
 
1328
static grub_err_t
1078
1329
grub_hfs_uuid (grub_device_t device, char **uuid)
1079
1330
{
1080
1331
  struct grub_hfs_data *data;
1109
1360
    .close = grub_hfs_close,
1110
1361
    .label = grub_hfs_label,
1111
1362
    .uuid = grub_hfs_uuid,
 
1363
    .mtime = grub_hfs_mtime,
 
1364
#ifdef GRUB_UTIL
 
1365
    .reserved_first_sector = 1,
 
1366
    .blocklist_install = 1,
 
1367
#endif
1112
1368
    .next = 0
1113
1369
  };
1114
1370