Update to upstream util-linux 2.20.1
[framework/base/util-linux-ng.git] / libblkid / src / superblocks / sysv.c
1 /*
2  * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
3  *
4  * This is written from sratch according to Linux kernel fs/sysv/super.c file.
5  * It seems that sysv probing code in libvolume_id and also in the original
6  * blkid is useless.
7  *
8  * This file may be redistributed under the terms of the
9  * GNU Lesser General Public License.
10  */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <stdint.h>
15 #include <stddef.h>
16
17 #include "superblocks.h"
18
19 #define XENIX_NICINOD                           100
20 #define XENIX_NICFREE                           100
21
22 struct xenix_super_block {
23         uint16_t        s_isize;
24         uint32_t        s_fsize;
25         uint16_t        s_nfree;
26         uint32_t        s_free[XENIX_NICFREE];
27         uint16_t        s_ninode;
28         uint16_t        s_inode[XENIX_NICINOD];
29         uint8_t         s_flock;
30         uint8_t         s_ilock;
31         uint8_t         s_fmod;
32         uint8_t         s_ronly;
33         uint32_t        s_time;
34         uint32_t        s_tfree;
35         uint16_t        s_tinode;
36         uint16_t        s_dinfo[4];
37         uint8_t         s_fname[6];
38         uint8_t         s_fpack[6];
39         uint8_t         s_clean;
40         uint8_t         s_fill[371];
41         uint32_t        s_magic;
42         uint32_t        s_type;
43 } __attribute__((packed));
44
45
46 #define SYSV_NICINOD                    100
47 #define SYSV_NICFREE                    50
48
49 struct sysv_super_block
50 {
51         uint16_t        s_isize;
52         uint16_t        s_pad0;
53         uint32_t        s_fsize;
54         uint16_t        s_nfree;
55         uint16_t        s_pad1;
56         uint32_t        s_free[SYSV_NICFREE];
57         uint16_t        s_ninode;
58         uint16_t        s_pad2;
59         uint16_t        s_inode[SYSV_NICINOD];
60         uint8_t         s_flock;
61         uint8_t         s_ilock;
62         uint8_t         s_fmod;
63         uint8_t         s_ronly;
64         uint32_t        s_time;
65         uint16_t        s_dinfo[4];
66         uint32_t        s_tfree;
67         uint16_t        s_tinode;
68         uint16_t        s_pad3;
69         uint8_t         s_fname[6];
70         uint8_t         s_fpack[6];
71         uint32_t        s_fill[12];
72         uint32_t        s_state;
73         uint32_t        s_magic;
74         uint32_t        s_type;
75 };
76
77 static int probe_xenix(blkid_probe pr, const struct blkid_idmag *mag)
78 {
79         struct xenix_super_block *sb;
80
81         sb = blkid_probe_get_sb(pr, mag, struct xenix_super_block);
82         if (!sb)
83                 return -1;
84         blkid_probe_set_label(pr, sb->s_fname, sizeof(sb->s_fname));
85         return 0;
86 }
87
88 #define SYSV_BLOCK_SIZE 1024
89
90 /* Note that we don't probe for Coherent FS, this FS does not have
91  * magic string. (It requires to probe fname/fpack field..)
92  */
93 static int probe_sysv(blkid_probe pr,
94                 const struct blkid_idmag *mag __attribute__((__unused__)))
95 {
96         struct sysv_super_block *sb;
97         int blocks[] = {0, 9, 15, 18};
98         size_t i;
99
100         for (i = 0; i < ARRAY_SIZE(blocks); i++) {
101                 int off = blocks[i] * SYSV_BLOCK_SIZE + SYSV_BLOCK_SIZE/2;
102
103                 sb = (struct sysv_super_block *)
104                         blkid_probe_get_buffer(pr,
105                                         off,
106                                         sizeof(struct sysv_super_block));
107                 if (!sb)
108                         return -1;
109
110                 if (sb->s_magic == cpu_to_le32(0xfd187e20) ||
111                     sb->s_magic == cpu_to_be32(0xfd187e20)) {
112
113                         if (blkid_probe_set_label(pr, sb->s_fname,
114                                                 sizeof(sb->s_fname)))
115                                 return -1;
116
117                         if (blkid_probe_set_magic(pr,
118                                         off + offsetof(struct sysv_super_block,
119                                                                 s_magic),
120                                         sizeof(sb->s_magic),
121                                         (unsigned char *) &sb->s_magic))
122                                 return -1;
123
124                         return 0;
125                 }
126         }
127         return 1;
128 }
129
130 const struct blkid_idinfo xenix_idinfo =
131 {
132         .name           = "xenix",
133         .usage          = BLKID_USAGE_FILESYSTEM,
134         .probefunc      = probe_xenix,
135         .magics         =
136         {
137                 { .magic = "\x2b\x55\x44", .len = 3, .kboff = 1, .sboff = 0x400 },
138                 { .magic = "\x44\x55\x2b", .len = 3, .kboff = 1, .sboff = 0x400 },
139                 { NULL }
140         }
141 };
142
143 const struct blkid_idinfo sysv_idinfo =
144 {
145         .name           = "sysv",
146         .usage          = BLKID_USAGE_FILESYSTEM,
147         .probefunc      = probe_sysv,
148
149         /* SYSV is BE and LE and superblock could be on four positions. It's
150          * simpler to probe for the magic string by .probefunc().
151          */
152         .magics         = BLKID_NONE_MAGIC
153 };
154