]> git.ipfire.org Git - thirdparty/util-linux.git/blame - mount/get_label_uuid.c
Imported from util-linux-2.12h tarball.
[thirdparty/util-linux.git] / mount / get_label_uuid.c
CommitLineData
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 */
23static inline int
24is_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 47int
2cccd0ff
KZ
48reiserfs_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
67int
68get_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