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