]>
Commit | Line | Data |
---|---|---|
c129767e | 1 | #ifndef HAVE_BLKID |
a5a16c68 KZ |
2 | /* |
3 | * Get label. Used by both mount and umount. | |
4 | */ | |
5 | #include <stdio.h> | |
6 | #include <fcntl.h> | |
7 | #include <unistd.h> | |
8 | #include <stdlib.h> | |
9 | #include <string.h> | |
10 | ||
11 | #include "linux_fs.h" | |
12 | #include "get_label_uuid.h" | |
13 | ||
14 | /* | |
15 | * See whether this device has (the magic of) a RAID superblock at the end. | |
16 | * If so, it probably is, or has been, part of a RAID array. | |
17 | * | |
18 | * For the moment this test is switched off - it causes problems. | |
19 | * "Checking for a disk label should only be done on the full raid, | |
20 | * not on the disks that form the raid array. This test causes a lot of | |
21 | * problems when run on my striped promise fasttrak 100 array." | |
22 | */ | |
23 | static inline int | |
24 | is_raid_partition(int fd) { | |
25 | #if 0 | |
26 | struct mdp_super_block mdsb; | |
27 | int n; | |
28 | ||
29 | /* hardcode 4096 here in various places, because that's | |
30 | what it's defined to be. Note that even if we used | |
31 | the actual kernel headers, sizeof(mdp_super_t) is | |
32 | slightly larger in the 2.2 kernel on 64-bit archs, | |
33 | so using that wouldn't work. */ | |
34 | lseek(fd, -4096, SEEK_END); /* Ignore possible error | |
35 | about return value overflow */ | |
36 | n = 4096; | |
37 | if (sizeof(mdsb) < n) | |
38 | n = sizeof(mdsb); | |
39 | if (read(fd, &mdsb, n) != n) | |
40 | return 1; /* error */ | |
41 | return (mdsbmagic(mdsb) == MD_SB_MAGIC); | |
42 | #else | |
43 | return 0; | |
44 | #endif | |
45 | } | |
46 | ||
c129767e | 47 | int |
2cccd0ff KZ |
48 | reiserfs_magic_version(const char *magic) { |
49 | int rc = 0; | |
50 | ||
51 | if (!strncmp(magic, REISERFS_SUPER_MAGIC_STRING, | |
52 | strlen(REISERFS_SUPER_MAGIC_STRING))) | |
53 | rc = 1; | |
54 | if (!strncmp(magic, REISER2FS_SUPER_MAGIC_STRING, | |
55 | strlen(REISER2FS_SUPER_MAGIC_STRING))) | |
56 | rc = 2; | |
57 | if (!strncmp(magic, REISER3FS_SUPER_MAGIC_STRING, | |
58 | strlen(REISER3FS_SUPER_MAGIC_STRING))) | |
59 | rc = 3; | |
60 | return rc; | |
c129767e KZ |
61 | } |
62 | ||
63 | /* | |
64 | * Get both label and uuid. | |
d26aa358 | 65 | * For now, only ext2, ext3, xfs, ocfs, ocfs2, reiserfs are supported |
c129767e | 66 | */ |
a5a16c68 KZ |
67 | int |
68 | get_label_uuid(const char *device, char **label, char *uuid) { | |
69 | int fd; | |
70 | int rv = 1; | |
71 | size_t namesize; | |
72 | struct ext2_super_block e2sb; | |
73 | struct xfs_super_block xfsb; | |
74 | struct jfs_super_block jfssb; | |
75 | struct ocfs_volume_header ovh; /* Oracle */ | |
76 | struct ocfs_volume_label olbl; | |
d26aa358 | 77 | struct ocfs2_super_block osb; |
c129767e | 78 | struct reiserfs_super_block reiserfssb; |
a5a16c68 KZ |
79 | |
80 | fd = open(device, O_RDONLY); | |
81 | if (fd < 0) | |
82 | return rv; | |
83 | ||
84 | /* If there is a RAID partition, or an error, ignore this partition */ | |
85 | if (is_raid_partition(fd)) { | |
86 | close(fd); | |
87 | return rv; | |
88 | } | |
89 | ||
90 | if (lseek(fd, 1024, SEEK_SET) == 1024 | |
91 | && read(fd, (char *) &e2sb, sizeof(e2sb)) == sizeof(e2sb) | |
92 | && (ext2magic(e2sb) == EXT2_SUPER_MAGIC)) { | |
93 | memcpy(uuid, e2sb.s_uuid, sizeof(e2sb.s_uuid)); | |
94 | namesize = sizeof(e2sb.s_volume_name); | |
95 | if ((*label = calloc(namesize + 1, 1)) != NULL) | |
96 | memcpy(*label, e2sb.s_volume_name, namesize); | |
97 | rv = 0; | |
98 | } | |
99 | else if (lseek(fd, 0, SEEK_SET) == 0 | |
100 | && read(fd, (char *) &xfsb, sizeof(xfsb)) == sizeof(xfsb) | |
101 | && (strncmp(xfsb.s_magic, XFS_SUPER_MAGIC, 4) == 0)) { | |
102 | memcpy(uuid, xfsb.s_uuid, sizeof(xfsb.s_uuid)); | |
103 | namesize = sizeof(xfsb.s_fname); | |
104 | if ((*label = calloc(namesize + 1, 1)) != NULL) | |
105 | memcpy(*label, xfsb.s_fname, namesize); | |
106 | rv = 0; | |
107 | } | |
108 | else if (lseek(fd, 0, SEEK_SET) == 0 | |
109 | && read(fd, (char *) &ovh, sizeof(ovh)) == sizeof(ovh) | |
110 | && (strncmp(ovh.signature, OCFS_MAGIC, sizeof(OCFS_MAGIC)) == 0) | |
111 | && (lseek(fd, 512, SEEK_SET) == 512) | |
112 | && read(fd, (char *) &olbl, sizeof(olbl)) == sizeof(olbl)) { | |
113 | uuid[0] = '\0'; | |
114 | namesize = ocfslabellen(olbl); | |
115 | if ((*label = calloc(namesize + 1, 1)) != NULL) | |
116 | memcpy(*label, olbl.label, namesize); | |
117 | rv = 0; | |
118 | } | |
119 | else if (lseek(fd, JFS_SUPER1_OFF, SEEK_SET) == JFS_SUPER1_OFF | |
120 | && read(fd, (char *) &jfssb, sizeof(jfssb)) == sizeof(jfssb) | |
121 | && (strncmp(jfssb.s_magic, JFS_MAGIC, 4) == 0)) { | |
2cccd0ff KZ |
122 | |
123 | /* The situation for jfs is rather messy. The structure of the | |
124 | superblock changed a few times, but there seems to be no good way | |
125 | to check what kind of sb we have. | |
126 | Old (OS/2 compatible) jfs filesystems don't have UUIDs and have | |
127 | an 11-byte label in s_fpack[]. | |
128 | Kernel 2.5.6 supports jfs v1; 2.5.8 supports v2; 2.5.18 has label/uuid. | |
129 | Kernel 2.4.20 supports jfs v2 with label/uuid. | |
130 | s_version will be 2 for new filesystems using an external log. | |
131 | Other new filesystems will have version 1. | |
132 | Label and UUID can be set by jfs_tune. */ | |
133 | ||
134 | /* Let us believe label/uuid on v2, and on v1 only when label agrees | |
135 | with s_fpack in the first 11 bytes. */ | |
136 | ||
137 | if (assemble4le(jfssb.s_version) == 1 && | |
138 | strncmp(jfssb.s_label, jfssb.s_fpack, 11) != 0) { | |
a5a16c68 KZ |
139 | memset(uuid, 0, 16); |
140 | namesize = sizeof(jfssb.s_fpack); | |
141 | if ((*label = calloc(namesize + 1, 1)) != NULL) | |
142 | memcpy(*label, jfssb.s_fpack, namesize); | |
143 | } else { | |
144 | memcpy(uuid, jfssb.s_uuid, sizeof(jfssb.s_uuid)); | |
145 | namesize = sizeof(jfssb.s_label); | |
146 | if ((*label = calloc(namesize + 1, 1)) != NULL) | |
147 | memcpy(*label, jfssb.s_label, namesize); | |
148 | } | |
149 | rv = 0; | |
150 | } | |
c129767e KZ |
151 | else if (lseek(fd, REISERFS_DISK_OFFSET_IN_BYTES, SEEK_SET) |
152 | == REISERFS_DISK_OFFSET_IN_BYTES | |
153 | && read(fd, (char *) &reiserfssb, sizeof(reiserfssb)) | |
154 | == sizeof(reiserfssb) | |
2cccd0ff KZ |
155 | /* Only 3.6.x format supers have labels or uuids. |
156 | Label and UUID can be set by reiserfstune -l/-u. */ | |
157 | && reiserfs_magic_version(reiserfssb.s_magic) > 1) { | |
c129767e KZ |
158 | namesize = sizeof (reiserfssb.s_label); |
159 | if ((*label = calloc(namesize + 1, 1)) != NULL) | |
160 | memcpy(*label, reiserfssb.s_label, namesize); | |
161 | memcpy(uuid, reiserfssb.s_uuid, sizeof (reiserfssb.s_uuid)); | |
162 | rv = 0; | |
163 | } | |
d26aa358 KZ |
164 | else { |
165 | int blksize, blkoff; | |
166 | ||
167 | for (blksize = OCFS2_MIN_BLOCKSIZE; | |
168 | blksize <= OCFS2_MAX_BLOCKSIZE; | |
169 | blksize <<= 1) { | |
170 | blkoff = blksize * OCFS2_SUPER_BLOCK_BLKNO; | |
171 | if (lseek(fd, blkoff, SEEK_SET) == blkoff | |
172 | && read(fd, (char *) &osb, sizeof(osb)) | |
173 | == sizeof(osb) | |
174 | && strncmp(osb.signature, | |
175 | OCFS2_SUPER_BLOCK_SIGNATURE, | |
176 | sizeof(OCFS2_SUPER_BLOCK_SIGNATURE)) | |
177 | == 0) { | |
178 | memcpy(uuid, osb.s_uuid, sizeof(osb.s_uuid)); | |
179 | namesize = sizeof(osb.s_label); | |
180 | if ((*label = calloc(namesize, 1)) != NULL) | |
181 | memcpy(*label, osb.s_label, namesize); | |
182 | rv = 0; | |
183 | break; | |
184 | } | |
185 | } | |
186 | } | |
a5a16c68 KZ |
187 | |
188 | close(fd); | |
189 | return rv; | |
190 | } | |
c129767e | 191 | #endif |