Upload Tizen:Base source
[framework/base/util-linux-ng.git] / shlibs / blkid / src / probers / iso9660.c
1 /*
2  * Copyright (C) 1999 by Andries Brouwer
3  * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
4  * Copyright (C) 2001 by Andreas Dilger
5  * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
6  * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
7  *
8  * Inspired also by libvolume_id by
9  *     Kay Sievers <kay.sievers@vrfy.org>
10  *
11  * This file may be redistributed under the terms of the
12  * GNU Lesser General Public License.
13  */
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <unistd.h>
17 #include <string.h>
18 #include <stdint.h>
19
20 #include "blkidP.h"
21
22 /* PVD - Primary volume descriptor */
23 struct iso_volume_descriptor {
24         unsigned char   vd_type;
25         unsigned char   vd_id[5];
26         unsigned char   vd_version;
27         unsigned char   flags;
28         unsigned char   system_id[32];
29         unsigned char   volume_id[32];
30         unsigned char   unused[8];
31         unsigned char   space_size[8];
32         unsigned char   escape_sequences[8];
33 } __attribute__((packed));
34
35 #define ISO_SUPERBLOCK_OFFSET           0x8000
36 #define ISO_SECTOR_SIZE                 0x800
37 #define ISO_VD_OFFSET                   (ISO_SUPERBLOCK_OFFSET + ISO_SECTOR_SIZE)
38 #define ISO_VD_SUPPLEMENTARY            0x2
39 #define ISO_VD_END                      0xff
40 #define ISO_VD_MAX                      16
41
42 struct high_sierra_volume_descriptor {
43         unsigned char   foo[8];
44         unsigned char   type;
45         unsigned char   id[5];
46         unsigned char   version;
47         unsigned char   unused1;
48         unsigned char   system_id[32];
49         unsigned char   volume_id[32];
50 } __attribute__((packed));
51
52 /* returns 1 if the begin of @ascii is equal to @utf16 string.
53  */
54 static int ascii_eq_utf16be(unsigned char *ascii,
55                         unsigned char *utf16, size_t len)
56 {
57         int a, u;
58
59         for (a = 0, u = 0; u < len; a++, u += 2) {
60                 if (utf16[u] != 0x0 || ascii[a] != utf16[u + 1])
61                         return 0;
62         }
63         return 1;
64 }
65
66 /* old High Sierra format */
67 static int probe_iso9660_hsfs(blkid_probe pr, const struct blkid_idmag *mag)
68 {
69         struct high_sierra_volume_descriptor *iso;
70
71         iso = blkid_probe_get_sb(pr, mag, struct high_sierra_volume_descriptor);
72         if (!iso)
73                 return -1;
74
75         blkid_probe_set_version(pr, "High Sierra");
76         blkid_probe_set_label(pr, iso->volume_id, sizeof(iso->volume_id));
77         return 0;
78 }
79
80 /* iso9660 [+ Microsoft Joliet Extension] */
81 static int probe_iso9660(blkid_probe pr, const struct blkid_idmag *mag)
82 {
83         struct iso_volume_descriptor *iso;
84         unsigned char label[32];
85         int i;
86         int off;
87
88         if (strcmp(mag->magic, "CDROM") == 0)
89                 return probe_iso9660_hsfs(pr, mag);
90
91         iso = blkid_probe_get_sb(pr, mag, struct iso_volume_descriptor);
92         if (!iso)
93                 return -1;
94
95         memcpy(label, iso->volume_id, sizeof(label));
96
97         /* Joliet Extension */
98         off = ISO_VD_OFFSET;
99         for (i = 0; i < ISO_VD_MAX; i++) {
100                 iso = (struct iso_volume_descriptor *)
101                         blkid_probe_get_buffer(pr,
102                                         off,
103                                         sizeof(struct iso_volume_descriptor));
104
105                 if (iso == NULL || iso->vd_type == ISO_VD_END)
106                         break;
107                 if (iso->vd_type != ISO_VD_SUPPLEMENTARY)
108                         continue;
109
110                 if (memcmp(iso->escape_sequences, "%/@", 3) == 0 ||
111                     memcmp(iso->escape_sequences, "%/C", 3) == 0 ||
112                     memcmp(iso->escape_sequences, "%/E", 3) == 0) {
113
114                         /* Is the Joliet (UTF16BE) label equal to the label in
115                          * the PVD? If yes, use PVD label.  The Jolied version
116                          * of the label could be trimed (because UTF16..).
117                          */
118                         if (ascii_eq_utf16be(label, iso->volume_id, 32))
119                                 break;
120
121                         blkid_probe_set_utf8label(pr,
122                                         iso->volume_id,
123                                         sizeof(iso->volume_id),
124                                         BLKID_ENC_UTF16BE);
125
126                         blkid_probe_set_version(pr, "Joliet Extension");
127                         goto has_label;
128                 }
129                 off += ISO_SECTOR_SIZE;
130         }
131
132         /* Joliet not found, let use standard iso label */
133         blkid_probe_set_label(pr, label, sizeof(label));
134
135 has_label:
136         return 0;
137 }
138
139
140 const struct blkid_idinfo iso9660_idinfo =
141 {
142         .name           = "iso9660",
143         .usage          = BLKID_USAGE_FILESYSTEM,
144         .probefunc      = probe_iso9660,
145         .flags          = BLKID_IDINFO_TOLERANT,
146         .magics         =
147         {
148                 { .magic = "CD001", .len = 5, .kboff = 32, .sboff = 1 },
149                 { .magic = "CDROM", .len = 5, .kboff = 32, .sboff = 9 },
150                 { NULL }
151         }
152 };
153