chiark / gitweb /
make: do not delete autotools generated file with distclean
[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
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #ifndef _GNU_SOURCE
22 #define _GNU_SOURCE 1
23 #endif
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <errno.h>
30 #include <ctype.h>
31
32 #include "libvolume_id.h"
33 #include "libvolume_id-private.h"
34
35 struct ocfs1_super_block_header {
36         uint32_t        minor_version;
37         uint32_t        major_version;
38         uint8_t         signature[128];
39         uint8_t         mount_point[128];
40         uint64_t        serial_num;
41         uint64_t        device_size;
42         uint64_t        start_off;
43         uint64_t        bitmap_off;
44         uint64_t        publ_off;
45         uint64_t        vote_off;
46         uint64_t        root_bitmap_off;
47         uint64_t        data_start_off;
48         uint64_t        root_bitmap_size;
49         uint64_t        root_off;
50         uint64_t        root_size;
51         uint64_t        cluster_size;
52         uint64_t        num_nodes;
53         uint64_t        num_clusters;
54         uint64_t        dir_node_size;
55         uint64_t        file_node_size;
56         uint64_t        internal_off;
57         uint64_t        node_cfg_off;
58         uint64_t        node_cfg_size;
59         uint64_t        new_cfg_off;
60         uint32_t        prot_bits;
61         int32_t         excl_mount;
62 } PACKED;
63
64 struct ocfs1_super_block_label {
65         struct ocfs1_disk_lock {
66                 uint32_t        curr_master;
67                 uint8_t         file_lock;
68                 uint8_t         compat_pad[3];
69                 uint64_t        last_write_time;
70                 uint64_t        last_read_time;
71                 uint32_t        writer_node_num;
72                 uint32_t        reader_node_num;
73                 uint64_t        oin_node_map;
74                 uint64_t        dlock_seq_num;
75         } PACKED disk_lock;
76         uint8_t         label[64];
77         uint16_t        label_len;
78         uint8_t         vol_id[16];
79         uint16_t        vol_id_len;
80         uint8_t         cluster_name[64];
81         uint16_t        cluster_name_len;
82 } PACKED;
83
84 struct ocfs2_super_block {
85         uint8_t         i_signature[8];
86         uint32_t        i_generation;
87         int16_t         i_suballoc_slot;
88         uint16_t        i_suballoc_bit;
89         uint32_t        i_reserved0;
90         uint32_t        i_clusters;
91         uint32_t        i_uid;
92         uint32_t        i_gid;
93         uint64_t        i_size;
94         uint16_t        i_mode;
95         uint16_t        i_links_count;
96         uint32_t        i_flags;
97         uint64_t        i_atime;
98         uint64_t        i_ctime;
99         uint64_t        i_mtime;
100         uint64_t        i_dtime;
101         uint64_t        i_blkno;
102         uint64_t        i_last_eb_blk;
103         uint32_t        i_fs_generation;
104         uint32_t        i_atime_nsec;
105         uint32_t        i_ctime_nsec;
106         uint32_t        i_mtime_nsec;
107         uint64_t        i_reserved1[9];
108         uint64_t        i_pad1;
109         uint16_t        s_major_rev_level;
110         uint16_t        s_minor_rev_level;
111         uint16_t        s_mnt_count;
112         int16_t         s_max_mnt_count;
113         uint16_t        s_state;
114         uint16_t        s_errors;
115         uint32_t        s_checkinterval;
116         uint64_t        s_lastcheck;
117         uint32_t        s_creator_os;
118         uint32_t        s_feature_compat;
119         uint32_t        s_feature_incompat;
120         uint32_t        s_feature_ro_compat;
121         uint64_t        s_root_blkno;
122         uint64_t        s_system_dir_blkno;
123         uint32_t        s_blocksize_bits;
124         uint32_t        s_clustersize_bits;
125         uint16_t        s_max_slots;
126         uint16_t        s_reserved1;
127         uint32_t        s_reserved2;
128         uint64_t        s_first_cluster_group;
129         uint8_t         s_label[64];
130         uint8_t         s_uuid[16];
131 } PACKED;
132
133 int volume_id_probe_ocfs1(struct volume_id *id, uint64_t off, uint64_t size)
134 {
135         const uint8_t *buf;
136         struct ocfs1_super_block_header *osh;
137         struct ocfs1_super_block_label *osl;
138
139         info("probing at offset 0x%" PRIx64 "\n", off);
140
141         buf = volume_id_get_buffer(id, off, 0x200);
142         if (buf == NULL)
143                 return -1;
144
145         osh = (struct ocfs1_super_block_header *) buf;
146         if (memcmp(osh->signature, "OracleCFS", 9) != 0)
147                 return -1;
148         snprintf(id->type_version, sizeof(id->type_version)-1,
149                  "%u.%u", osh->major_version, osh->minor_version);
150
151         dbg("found OracleCFS signature, now reading label\n");
152         buf = volume_id_get_buffer(id, off + 0x200, 0x200);
153         if (buf == NULL)
154                 return -1;
155
156         osl = (struct ocfs1_super_block_label *) buf;
157         volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
158         if (osl->label_len <= 64) {
159                 volume_id_set_label_raw(id, osl->label, 64);
160                 volume_id_set_label_string(id, osl->label, 64);
161         }
162         if (osl->vol_id_len == 16)
163                 volume_id_set_uuid(id, osl->vol_id, 0, UUID_DCE);
164         id->type = "ocfs";
165         return 0;
166 }
167
168 #define OCFS2_MAX_BLOCKSIZE             0x1000
169 #define OCFS2_SUPER_BLOCK_BLKNO         2
170
171 int volume_id_probe_ocfs2(struct volume_id *id, uint64_t off, uint64_t size)
172 {
173         const uint8_t *buf;
174         struct ocfs2_super_block *os;
175         size_t blksize;
176
177         info("probing at offset 0x%" PRIx64 "\n", off);
178
179         for (blksize = 0x200; blksize <= OCFS2_MAX_BLOCKSIZE; blksize <<= 1) {
180                 buf = volume_id_get_buffer(id, off + OCFS2_SUPER_BLOCK_BLKNO * blksize, 0x200);
181                 if (buf == NULL)
182                         return -1;
183
184                 os = (struct ocfs2_super_block *) buf;
185                 if (memcmp(os->i_signature, "OCFSV2", 6) != 0)
186                         continue;
187
188                 volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
189                 volume_id_set_label_raw(id, os->s_label, 64);
190                 volume_id_set_label_string(id, os->s_label, 64);
191                 volume_id_set_uuid(id, os->s_uuid, 0, UUID_DCE);
192                 snprintf(id->type_version, sizeof(id->type_version)-1,
193                          "%u.%u", os->s_major_rev_level, os->s_minor_rev_level);
194                 id->type = "ocfs2";
195                 return 0;
196         }
197         return -1;
198 }