1 /*
2  * volume_id - reads filesystem label and uuid
3  *
4  * Copyright (C) 2005 Kay Sievers <kay.sievers@vrfy.org>
5  *
6  *	This program is free software; you can redistribute it and/or modify it
7  *	under the terms of the GNU General Public License as published by the
8  *	Free Software Foundation version 2 of the License.
9  */
10 
11 #ifndef _GNU_SOURCE
12 #define _GNU_SOURCE 1
13 #endif
14 
15 #ifdef HAVE_CONFIG_H
16 #  include <config.h>
17 #endif
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <ctype.h>
25 
26 #include "libvolume_id.h"
27 #include "util.h"
28 
29 #define SYSV_NICINOD			100
30 #define SYSV_NICFREE			50
31 
32 struct sysv_super
33 {
34 	uint16_t	s_isize;
35 	uint16_t	s_pad0;
36 	uint32_t	s_fsize;
37 	uint16_t	s_nfree;
38 	uint16_t	s_pad1;
39 	uint32_t	s_free[SYSV_NICFREE];
40 	uint16_t	s_ninode;
41 	uint16_t	s_pad2;
42 	uint16_t	s_inode[SYSV_NICINOD];
43 	uint8_t		s_flock;
44 	uint8_t		s_ilock;
45 	uint8_t		s_fmod;
46 	uint8_t		s_ronly;
47 	uint32_t	s_time;
48 	uint16_t	s_dinfo[4];
49 	uint32_t	s_tfree;
50 	uint16_t	s_tinode;
51 	uint16_t	s_pad3;
52 	uint8_t		s_fname[6];
53 	uint8_t		s_fpack[6];
54 	uint32_t	s_fill[12];
55 	uint32_t	s_state;
56 	uint32_t	s_magic;
57 	uint32_t	s_type;
58 } PACKED;
59 
60 #define XENIX_NICINOD				100
61 #define XENIX_NICFREE				100
62 
63 struct xenix_super {
64 	uint16_t	s_isize;
65 	uint32_t	s_fsize;
66 	uint16_t	s_nfree;
67 	uint32_t	s_free[XENIX_NICFREE];
68 	uint16_t	s_ninode;
69 	uint16_t	s_inode[XENIX_NICINOD];
70 	uint8_t		s_flock;
71 	uint8_t		s_ilock;
72 	uint8_t		s_fmod;
73 	uint8_t		s_ronly;
74 	uint32_t	s_time;
75 	uint32_t	s_tfree;
76 	uint16_t	s_tinode;
77 	uint16_t	s_dinfo[4];
78 	uint8_t		s_fname[6];
79 	uint8_t		s_fpack[6];
80 	uint8_t		s_clean;
81 	uint8_t		s_fill[371];
82 	uint32_t	s_magic;
83 	uint32_t	s_type;
84 } PACKED;
85 
86 #define SYSV_SUPERBLOCK_BLOCK			0x01
87 #define SYSV_MAGIC				0xfd187e20
88 #define XENIX_SUPERBLOCK_BLOCK			0x18
89 #define XENIX_MAGIC				0x2b5544
90 #define SYSV_MAX_BLOCKSIZE			0x800
91 
volume_id_probe_sysv(struct volume_id * id,uint64_t off,uint64_t size)92 int volume_id_probe_sysv(struct volume_id *id, uint64_t off, uint64_t size)
93 {
94 	struct sysv_super *vs;
95 	struct xenix_super *xs;
96 	unsigned int boff;
97 
98 	info("probing at offset 0x%llx", (unsigned long long) off);
99 
100 	for (boff = 0x200; boff <= SYSV_MAX_BLOCKSIZE; boff <<= 1) {
101 		vs = (struct sysv_super *)
102 			volume_id_get_buffer(id, off + (boff * SYSV_SUPERBLOCK_BLOCK), 0x200);
103 		if (vs == NULL)
104 			return -1;
105 
106 		if (vs->s_magic == cpu_to_le32(SYSV_MAGIC) || vs->s_magic == cpu_to_be32(SYSV_MAGIC)) {
107 			volume_id_set_label_raw(id, vs->s_fname, 6);
108 			volume_id_set_label_string(id, vs->s_fname, 6);
109 			id->type = "sysv";
110 			goto found;
111 		}
112 	}
113 
114 	for (boff = 0x200; boff <= SYSV_MAX_BLOCKSIZE; boff <<= 1) {
115 		xs = (struct xenix_super *)
116 			volume_id_get_buffer(id, off + (boff + XENIX_SUPERBLOCK_BLOCK), 0x200);
117 		if (xs == NULL)
118 			return -1;
119 
120 		if (xs->s_magic == cpu_to_le32(XENIX_MAGIC) || xs->s_magic == cpu_to_be32(XENIX_MAGIC)) {
121 			volume_id_set_label_raw(id, xs->s_fname, 6);
122 			volume_id_set_label_string(id, xs->s_fname, 6);
123 			id->type = "xenix";
124 			goto found;
125 		}
126 	}
127 
128 	return -1;
129 
130 found:
131 	volume_id_set_usage(id, VOLUME_ID_FILESYSTEM);
132 	return 0;
133 }
134