chiark / gitweb /
udevadm: add --version --help options to man page, hide them as commands
[elogind.git] / extras / volume_id / lib / ocfs.c
1 /*
2  * volume_id - reads filesystem label and uuid
3  *
4  * Copyright (C) 2004 Andre Masella <andre@masella.no-ip.org>
5  * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
6  *
7  *      This program is free software; you can redistribute it and/or modify it
8  *      under the terms of the GNU General Public License as published by the
9  *      Free Software Foundation version 2 of the License.
10  */
11
12 #ifndef _GNU_SOURCE
13 #define _GNU_SOURCE 1
14 #endif
15
16 #ifdef HAVE_CONFIG_H
17 #  include <config.h>
18 #endif
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <ctype.h>
26
27 #include "libvolume_id.h"
28 #include "libvolume_id-private.h"
29 #include "util.h"
30
31
32 struct ocfs1_super_block_header {
33         uint32_t        minor_version;
34         uint32_t        major_version;
35         uint8_t         signature[128];
36         uint8_t         mount_point[128];
37         uint64_t        serial_num;
38         uint64_t        device_size;
39         uint64_t        start_off;
40         uint64_t        bitmap_off;
41         uint64_t        publ_off;
42         uint64_t        vote_off;
43         uint64_t        root_bitmap_off;
44         uint64_t        data_start_off;
45         uint64_t        root_bitmap_size;
46         uint64_t        root_off;
47         uint64_t        root_size;
48         uint64_t        cluster_size;
49         uint64_t        num_nodes;
50         uint64_t        num_clusters;
51         uint64_t        dir_node_size;
52         uint64_t        file_node_size;
53         uint64_t        internal_off;
54         uint64_t        node_cfg_off;
55         uint64_t        node_cfg_size;
56         uint64_t        new_cfg_off;
57         uint32_t        prot_bits;
58         int32_t         excl_mount;
59 } PACKED;
60
61 struct ocfs1_super_block_label {
62         struct ocfs1_disk_lock {
63                 uint32_t        curr_master;
64                 uint8_t         file_lock;
65                 uint8_t         compat_pad[3];
66                 uint64_t        last_write_time;
67                 uint64_t        last_read_time;
68                 uint32_t        writer_node_num;
69                 uint32_t        reader_node_num;
70                 uint64_t        oin_node_map;
71                 uint64_t        dlock_seq_num;
72         } PACKED disk_lock;
73         uint8_t         label[64];
74         uint16_t        label_len;
75         uint8_t         vol_id[16];
76         uint16_t        vol_id_len;
77         uint8_t         cluster_name[64];
78         uint16_t        cluster_name_len;
79 } PACKED;
80
81 struct ocfs2_super_block {
82         uint8_t         i_signature[8];
83         uint32_t        i_generation;
84         int16_t         i_suballoc_slot;
85         uint16_t        i_suballoc_bit;
86         uint32_t        i_reserved0;
87         uint32_t        i_clusters;
88         uint32_t        i_uid;
89         uint32_t        i_gid;
90         uint64_t        i_size;
91         uint16_t        i_mode;
92         uint16_t        i_links_count;
93         uint32_t        i_flags;
94         uint64_t        i_atime;
95         uint64_t        i_ctime;
96         uint64_t        i_mtime;
97         uint64_t        i_dtime;
98         uint64_t        i_blkno;
99         uint64_t        i_last_eb_blk;
100         uint32_t        i_fs_generation;
101         uint32_t        i_atime_nsec;
102         uint32_t        i_ctime_nsec;
103         uint32_t        i_mtime_nsec;
104         uint64_t        i_reserved1[9];
105         uint64_t        i_pad1;
106         uint16_t        s_major_rev_level;
107         uint16_t        s_minor_rev_level;
108         uint16_t        s_mnt_count;
109         int16_t         s_max_mnt_count;
110         uint16_t        s_state;
111         uint16_t        s_errors;
112         uint32_t        s_checkinterval;
113         uint64_t        s_lastcheck;
114         uint32_t        s_creator_os;
115         uint32_t        s_feature_compat;
116         uint32_t        s_feature_incompat;
117         uint32_t        s_feature_ro_compat;
118         uint64_t        s_root_blkno;
119         uint64_t        s_system_dir_blkno;
120         uint32_t        s_blocksize_bits;
121         uint32_t        s_clustersize_bits;
122         uint16_t        s_max_slots;
123         uint16_t        s_reserved1;
124         uint32_t        s_reserved2;
125         uint64_t        s_first_cluster_group;
126         uint8_t         s_label[64];
127         uint8_t         s_uuid[16];
128 } PACKED;
129
130 int volume_id_probe_ocfs1(struct volume_id *id, uint64_t off, uint64_t size)
131 {
132         const uint8_t *buf;
133         struct ocfs1_super_block_header *osh;
134         struct ocfs1_super_block_label *osl;
135
136         info("probing at offset 0x%llx\n", (unsigned long long) off);
137
138         buf = volume_id_get_buffer(id, off, 0x200);
139         if (buf == NULL)
140                 return -1;
141
142         osh = (struct ocfs1_super_block_header *) buf;
143         if (memcmp(osh->signature, "OracleCFS", 9) != 0)
144                 return -1;
145         snprintf(id->type_version, sizeof(id->type_version)-1,
146                  "%u.%u", osh->major_version, osh->minor_version);
147
148         dbg("found OracleCFS signature, now reading label\n");
149         buf = volume_id_get_buffer(id, off + 0x200, 0x200);
150         if (buf == NULL)
151                 return -1;
152
153         osl = (struct ocfs1_super_block_label *) buf;
154         volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
155         if (osl->label_len <= 64) {
156                 volume_id_set_label_raw(id, osl->label, 64);
157                 volume_id_set_label_string(id, osl->label, 64);
158         }
159         if (osl->vol_id_len == 16)
160                 volume_id_set_uuid(id, osl->vol_id, 0, UUID_DCE);
161         id->type = "ocfs";
162         return 0;
163 }
164
165 #define OCFS2_MAX_BLOCKSIZE             0x1000
166 #define OCFS2_SUPER_BLOCK_BLKNO         2
167
168 int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off, uint64_t size)
169 {
170         const uint8_t *buf;
171         struct ocfs2_super_block *os;
172         size_t blksize;
173
174         info("probing at offset 0x%llx\n", (unsigned long long) off);
175
176         for (blksize = 0x200; blksize <= OCFS2_MAX_BLOCKSIZE; blksize <<= 1) {
177                 buf = volume_id_get_buffer(id, off + OCFS2_SUPER_BLOCK_BLKNO * blksize, 0x200);
178                 if (buf == NULL)
179                         return -1;
180
181                 os = (struct ocfs2_super_block *) buf;
182                 if (memcmp(os->i_signature, "OCFSV2", 6) != 0)
183                         continue;
184
185                 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
186                 volume_id_set_label_raw(id, os->s_label, 64);
187                 volume_id_set_label_string(id, os->s_label, 64);
188                 volume_id_set_uuid(id, os->s_uuid, 0, UUID_DCE);
189                 snprintf(id->type_version, sizeof(id->type_version)-1,
190                          "%u.%u", os->s_major_rev_level, os->s_minor_rev_level);
191                 id->type = "ocfs2";
192                 return 0;
193         }
194         return -1;
195 }