1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
|
/* vi: set ts=4:
*
* mke2fs.c - Create an ext2 filesystem image.
*
* Copyright 2006 Rob Landley <rob@landley.net>
*/
#include "toys.h"
// Stuff defined in linux/ext2_fs.h
#define EXT2_SUPER_MAGIC 0xEF53
struct ext2_inode {
uint16_t mode; // File mode
uint16_t uid; // Low 16 bits of Owner Uid
uint32_t size; // Size in bytes
uint32_t atime; // Access time
uint32_t ctime; // Creation time
uint32_t mtime; // Modification time
uint32_t dtime; // Deletion Time
uint16_t gid; // Low 16 bits of Group Id
uint16_t links_count; // Links count
uint32_t blocks; // Blocks count
uint32_t flags; // File flags
uint32_t reserved1;
uint32_t block[15]; // Pointers to blocks
uint32_t generation; // File version (for NFS)
uint32_t file_acl; // File ACL
uint32_t dir_acl; // Directory ACL
uint32_t faddr; // Fragment address
uint8_t frag; // Fragment number
uint8_t fsize; // Fragment size
uint16_t pad1;
uint16_t uid_high; // High bits of uid
uint16_t gid_high; // High bits of gid
uint32_t reserved2;
};
struct ext2_super_block {
uint32_t inodes_count; // Inodes count
uint32_t blocks_count; // Blocks count
uint32_t r_blocks_count; // Reserved blocks count
uint32_t free_blocks_count; // Free blocks count
uint32_t free_inodes_count; // Free inodes count
uint32_t first_data_block; // First Data Block
uint32_t log_block_size; // Block size
uint32_t log_frag_size; // Fragment size
uint32_t blocks_per_group; // # Blocks per group
uint32_t frags_per_group; // # Fragments per group
uint32_t inodes_per_group; // # Inodes per group
uint32_t mtime; // Mount time
uint32_t wtime; // Write time
uint16_t mnt_count; // Mount count
uint16_t max_mnt_count; // Maximal mount count
uint16_t magic; // Magic signature
uint16_t state; // File system state
uint16_t errors; // Behaviour when detecting errors
uint16_t minor_rev_level; // minor revision level
uint32_t lastcheck; // time of last check
uint32_t checkinterval; // max. time between checks
uint32_t creator_os; // OS
uint32_t rev_level; // Revision level
uint16_t def_resuid; // Default uid for reserved blocks
uint16_t def_resgid; // Default gid for reserved blocks
uint32_t first_ino; // First non-reserved inode
uint16_t inode_size; // size of inode structure
uint16_t block_group_nr; // block group # of this superblock
uint32_t feature_compat; // compatible feature set
uint32_t feature_incompat; // incompatible feature set
uint32_t feature_ro_compat; // readonly-compatible feature set
char uuid[16]; // 128-bit uuid for volume
char volume_name[16]; // volume name
char last_mounted[64]; // directory where last mounted
uint32_t alg_usage_bitmap; // For compression
// For EXT2_COMPAT_PREALLOC
uint8_t prealloc_blocks; // Nr of blocks to try to preallocate
uint8_t prealloc_dir_blocks; //Nr to preallocate for dirs
uint16_t padding1;
// For EXT3_FEATURE_COMPAT_HAS_JOURNAL
uint8_t journal_uuid[16]; // uuid of journal superblock
uint32_t journal_inum; // inode number of journal file
uint32_t journal_dev; // device number of journal file
uint32_t last_orphan; // start of list of inodes to delete
uint32_t hash_seed[4]; // HTREE hash seed
uint8_t def_hash_version; // Default hash version to use
uint8_t padding2[3];
uint32_t default_mount_opts;
uint32_t first_meta_bg; // First metablock block group
uint32_t reserved[190]; // Padding to the end of the block
};
#define EXT2_FEATURE_COMPAT_DIR_PREALLOC 0x0001
#define EXT2_FEATURE_COMPAT_IMAGIC_INODES 0x0002
#define EXT3_FEATURE_COMPAT_HAS_JOURNAL 0x0004
#define EXT2_FEATURE_COMPAT_EXT_ATTR 0x0008
#define EXT2_FEATURE_COMPAT_RESIZE_INO 0x0010
#define EXT2_FEATURE_COMPAT_DIR_INDEX 0x0020
#define EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER 0x0001
#define EXT2_FEATURE_RO_COMPAT_LARGE_FILE 0x0002
#define EXT2_FEATURE_RO_COMPAT_BTREE_DIR 0x0004
#define EXT2_FEATURE_INCOMPAT_COMPRESSION 0x0001
#define EXT2_FEATURE_INCOMPAT_FILETYPE 0x0002
#define EXT3_FEATURE_INCOMPAT_RECOVER 0x0004
#define EXT3_FEATURE_INCOMPAT_JOURNAL_DEV 0x0008
#define EXT2_FEATURE_INCOMPAT_META_BG 0x0010
#define EXT2_NAME_LEN 255
struct ext2_dir_entry_2 {
uint32_t inode; // Inode number
uint16_t rec_len; // Directory entry length
uint8_t name_len; // Name length
uint8_t file_type;
char name[255]; // File name
};
// Ext2 directory file types. Only the low 3 bits are used. The
// other bits are reserved for now.
enum {
EXT2_FT_UNKNOWN,
EXT2_FT_REG_FILE,
EXT2_FT_DIR,
EXT2_FT_CHRDEV,
EXT2_FT_BLKDEV,
EXT2_FT_FIFO,
EXT2_FT_SOCK,
EXT2_FT_SYMLINK,
EXT2_FT_MAX
};
// b - block size (1024, 2048, 4096)
// F - force (run on mounted device or non-block device)
// i - bytes per inode
// N - number of inodes
// m - reserved blocks percentage
// n - Don't write
// q - quiet
// L - volume label
// M - last mounted path
// o - creator os
// j - create journal
// J - journal options (size=1024-102400 blocks,device=)
// device=/dev/blah or LABEL=label UUID=uuid
// E - extended options (stride=stripe-size blocks)
// O - none,dir_index,filetype,has_journal,journal_dev,sparse_super
// This is what's in a UUID according to the spec at
// http://www.opengroup.org/onlinepubs/9629399/apdxa.htm
//struct uuid {
// uint32_t time_low;
// uint16_t time_mid;
// uint16_t time_hi_and_version;
// uint8_t clock_seq_hi_and_reserved;
// uint8_t clock_seq_low;
// uint8_t node[6];
//};
// According to http://www.opengroup.org/onlinepubs/9629399/apdxa.htm
// we should generate a uuid structure by reading a clock with 100 nanosecond
// precision, normalizing it to the start of the gregorian calendar in 1582,
// and looking up our eth0 mac address.
//
// On the other hand, we have 128 bits to come up with a unique identifier, of
// which 6 have a defined value. /dev/urandom it is.
void create_uuid(char *uuid)
{
// Read 128 random bytes
int fd = xopen("/dev/urandom", O_RDONLY);
xreadall(fd, uuid, 16);
close(fd);
// Claim to be a DCE format UUID.
uuid[6] = (uuid[6] & 0x0F) | 0x40;
uuid[8] = (uuid[8] & 0x3F) | 0x80;
// rfc2518 section 6.4.1 suggests if we're not using a macaddr, we should
// set bit 1 of the node ID, which is the mac multicast bit. This means we
// should never collide with anybody actually using a macaddr.
uuid[11] = uuid[11] | 128;
}
int mke2fs_main(void)
{
struct ext2_super_block *sb = xzalloc(sizeof(struct ext2_super_block));
int temp;
// Handle command line arguments.
if (!*toys.optargs || (!CFG_MKE2FS_GEN && toys.optargs[1])) usage_exit();
if (CFG_MKE2FS_GEN && toys.optargs[1]) {
temp = O_RDWR|O_CREAT;
xaccess(toys.optargs[1], R_OK);
} else temp = O_RDWR;
if (toy.mke2fs.blocksize!=1024 && toy.mke2fs.blocksize!=2048
&& toy.mke2fs.blocksize!=4096) error_exit("bad blocksize");
// For mke?fs, open file. For gene?fs, create file.
toy.mke2fs.fsfd = xcreate(*toys.optargs, temp, 0777);
// We don't autodetect block size from external journaling devices, instead
// we write our block size to that journaling device. (If they want a
// specific block size, they have the -b option.)
// What's the deal with fs_type?
// line 1059
// We skip the first 1k (to avoid the boot sector, if any). Use this to
// figure out if this file is seekable.
if(-1 == lseek(toy.mke2fs.fsfd, 1024, SEEK_SET)) {
toy.mke2fs.noseek=1;
xwrite(toy.mke2fs.fsfd, sb, 1024);
}
// Fill out superblock structure
sb->rev_level = SWAP_LE32(1);
sb->feature_incompat = SWAP_LE32(EXT2_FEATURE_INCOMPAT_FILETYPE);
sb->feature_ro_compat = SWAP_LE32(EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER);
// If we're called as mke3fs or mkfs.ext3, do a journal.
if (strchr(toys.which->name,'3'))
sb->feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
// Write superblock to disk.
xwrite(toy.mke2fs.fsfd, sb, 3072); // 4096-1024
return 0;
}
|