chiark / gitweb /
763b79cb0b7648119f7467c9b5f6de5db54bf08a
[elogind.git] / extras / volume_id / volume_id / ufs.c
1 /*
2  * volume_id - reads filesystem label and uuid
3  *
4  * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
5  *
6  *      This library is free software; you can redistribute it and/or
7  *      modify it under the terms of the GNU Lesser General Public
8  *      License as published by the Free Software Foundation; either
9  *      version 2.1 of the License, or (at your option) any later version.
10  *
11  *      This library is distributed in the hope that it will be useful,
12  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  *      Lesser General Public License for more details.
15  *
16  *      You should have received a copy of the GNU Lesser General Public
17  *      License along with this library; if not, write to the Free Software
18  *      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */
20
21 #ifndef _GNU_SOURCE
22 #define _GNU_SOURCE 1
23 #endif
24
25 #ifdef HAVE_CONFIG_H
26 #  include <config.h>
27 #endif
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <ctype.h>
35
36 #include "volume_id.h"
37 #include "logging.h"
38 #include "util.h"
39 #include "ufs.h"
40
41 struct ufs_super_block {
42         uint32_t        fs_link;
43         uint32_t        fs_rlink;
44         uint32_t        fs_sblkno;
45         uint32_t        fs_cblkno;
46         uint32_t        fs_iblkno;
47         uint32_t        fs_dblkno;
48         uint32_t        fs_cgoffset;
49         uint32_t        fs_cgmask;
50         uint32_t        fs_time;
51         uint32_t        fs_size;
52         uint32_t        fs_dsize;
53         uint32_t        fs_ncg; 
54         uint32_t        fs_bsize;
55         uint32_t        fs_fsize;
56         uint32_t        fs_frag;
57         uint32_t        fs_minfree;
58         uint32_t        fs_rotdelay;
59         uint32_t        fs_rps; 
60         uint32_t        fs_bmask;
61         uint32_t        fs_fmask;
62         uint32_t        fs_bshift;
63         uint32_t        fs_fshift;
64         uint32_t        fs_maxcontig;
65         uint32_t        fs_maxbpg;
66         uint32_t        fs_fragshift;
67         uint32_t        fs_fsbtodb;
68         uint32_t        fs_sbsize;
69         uint32_t        fs_csmask;
70         uint32_t        fs_csshift;
71         uint32_t        fs_nindir;
72         uint32_t        fs_inopb;
73         uint32_t        fs_nspf;
74         uint32_t        fs_optim;
75         uint32_t        fs_npsect_state;
76         uint32_t        fs_interleave;
77         uint32_t        fs_trackskew;
78         uint32_t        fs_id[2];
79         uint32_t        fs_csaddr;
80         uint32_t        fs_cssize;
81         uint32_t        fs_cgsize;
82         uint32_t        fs_ntrak;
83         uint32_t        fs_nsect;
84         uint32_t        fs_spc; 
85         uint32_t        fs_ncyl;
86         uint32_t        fs_cpg;
87         uint32_t        fs_ipg;
88         uint32_t        fs_fpg;
89         struct ufs_csum {
90                 uint32_t        cs_ndir;
91                 uint32_t        cs_nbfree;
92                 uint32_t        cs_nifree;
93                 uint32_t        cs_nffree;
94         } __attribute__((__packed__)) fs_cstotal;
95         int8_t          fs_fmod;
96         int8_t          fs_clean;
97         int8_t          fs_ronly;
98         int8_t          fs_flags;
99         union {
100                 struct {
101                         int8_t  fs_fsmnt[512];
102                         uint32_t        fs_cgrotor;
103                         uint32_t        fs_csp[31];
104                         uint32_t        fs_maxcluster;
105                         uint32_t        fs_cpc;
106                         uint16_t        fs_opostbl[16][8];
107                 } __attribute__((__packed__)) fs_u1;
108                 struct {
109                         int8_t          fs_fsmnt[468];
110                         uint8_t         fs_volname[32];
111                         uint64_t        fs_swuid;
112                         int32_t         fs_pad;
113                         uint32_t        fs_cgrotor;
114                         uint32_t        fs_ocsp[28];
115                         uint32_t        fs_contigdirs;
116                         uint32_t        fs_csp; 
117                         uint32_t        fs_maxcluster;
118                         uint32_t        fs_active;
119                         int32_t         fs_old_cpc;
120                         int32_t         fs_maxbsize;
121                         int64_t         fs_sparecon64[17];
122                         int64_t         fs_sblockloc;
123                         struct ufs2_csum_total {
124                                 uint64_t        cs_ndir;
125                                 uint64_t        cs_nbfree;
126                                 uint64_t        cs_nifree;
127                                 uint64_t        cs_nffree;
128                                 uint64_t        cs_numclusters;
129                                 uint64_t        cs_spare[3];
130                         } __attribute__((__packed__)) fs_cstotal;
131                         struct ufs_timeval {
132                                 int32_t         tv_sec;
133                                 int32_t         tv_usec;
134                         } __attribute__((__packed__)) fs_time;
135                         int64_t         fs_size;
136                         int64_t         fs_dsize;
137                         uint64_t        fs_csaddr;
138                         int64_t         fs_pendingblocks;
139                         int32_t         fs_pendinginodes;
140                 } __attribute__((__packed__)) fs_u2;
141         }  fs_u11;
142         union {
143                 struct {
144                         int32_t         fs_sparecon[53];
145                         int32_t         fs_reclaim;
146                         int32_t         fs_sparecon2[1];
147                         int32_t         fs_state;
148                         uint32_t        fs_qbmask[2];
149                         uint32_t        fs_qfmask[2];
150                 } __attribute__((__packed__)) fs_sun;
151                 struct {
152                         int32_t         fs_sparecon[53];
153                         int32_t         fs_reclaim;
154                         int32_t         fs_sparecon2[1];
155                         uint32_t        fs_npsect;
156                         uint32_t        fs_qbmask[2];
157                         uint32_t        fs_qfmask[2];
158                 } __attribute__((__packed__)) fs_sunx86;
159                 struct {
160                         int32_t         fs_sparecon[50];
161                         int32_t         fs_contigsumsize;
162                         int32_t         fs_maxsymlinklen;
163                         int32_t         fs_inodefmt;
164                         uint32_t        fs_maxfilesize[2];
165                         uint32_t        fs_qbmask[2];
166                         uint32_t        fs_qfmask[2];
167                         int32_t         fs_state;
168                 } __attribute__((__packed__)) fs_44;
169         } fs_u2;
170         int32_t         fs_postblformat;
171         int32_t         fs_nrpos;
172         int32_t         fs_postbloff;
173         int32_t         fs_rotbloff;
174         uint32_t        fs_magic;
175         uint8_t         fs_space[1];
176 } __attribute__((__packed__));
177
178 #define UFS_MAGIC                       0x00011954
179 #define UFS2_MAGIC                      0x19540119
180 #define UFS_MAGIC_FEA                   0x00195612
181 #define UFS_MAGIC_LFN                   0x00095014
182
183 int volume_id_probe_ufs(struct volume_id *id, uint64_t off)
184 {
185         uint32_t magic;
186         int i;
187         struct ufs_super_block *ufs;
188         int offsets[] = {0, 8, 64, 256, -1};
189
190         dbg("probing at offset 0x%llx", (unsigned long long) off);
191
192         for (i = 0; offsets[i] >= 0; i++) {     
193                 ufs = (struct ufs_super_block *) volume_id_get_buffer(id, off + (offsets[i] * 0x400), 0x800);
194                 if (ufs == NULL)
195                         return -1;
196
197                 dbg("offset 0x%x", offsets[i] * 0x400);
198                 magic = be32_to_cpu(ufs->fs_magic);
199                 if ((magic == UFS_MAGIC) ||
200                     (magic == UFS2_MAGIC) ||
201                     (magic == UFS_MAGIC_FEA) ||
202                     (magic == UFS_MAGIC_LFN)) {
203                         dbg("magic 0x%08x(be)", magic);
204                         goto found;
205                 }
206                 magic = le32_to_cpu(ufs->fs_magic);
207                 if ((magic == UFS_MAGIC) ||
208                     (magic == UFS2_MAGIC) ||
209                     (magic == UFS_MAGIC_FEA) ||
210                     (magic == UFS_MAGIC_LFN)) {
211                         dbg("magic 0x%08x(le)", magic);
212                         goto found;
213                 }
214         }
215         return -1;
216
217 found:
218         volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
219         id->type = "ufs";
220
221         return 0;
222 }