blob: 5b587c90e37b3d122c23087111bc6837ca103405 [file] [log] [blame]
swissChilief829f32021-06-13 20:00:54 -07001#pragma once
2
3#include <vfs.h>
4
5struct ext2_superblock
6{
swissChilib7ef65d2021-07-17 12:51:52 -07007 /// Total number of inodes
swissChilief829f32021-06-13 20:00:54 -07008 uint total_inodes;
swissChilib7ef65d2021-07-17 12:51:52 -07009
10 /// Total number of blocks
swissChilief829f32021-06-13 20:00:54 -070011 uint total_blocks;
swissChilib7ef65d2021-07-17 12:51:52 -070012
13 /// Number of blocks reserved for superuser
swissChilief829f32021-06-13 20:00:54 -070014 uint blocks_reserved_for_superuser;
swissChilib7ef65d2021-07-17 12:51:52 -070015
16 /// Number of unallocated blocks
swissChilief829f32021-06-13 20:00:54 -070017 uint unallocated_blocks;
swissChilib7ef65d2021-07-17 12:51:52 -070018
19 /// Number of unallocated inodes
swissChilief829f32021-06-13 20:00:54 -070020 uint unallocated_inodes;
swissChilib7ef65d2021-07-17 12:51:52 -070021
22 /// Block number containing the superblock
swissChilief829f32021-06-13 20:00:54 -070023 uint superblock_block_number;
swissChilib7ef65d2021-07-17 12:51:52 -070024
25 /// the number to shift 1024 to the left by to get the block size
swissChilief829f32021-06-13 20:00:54 -070026 uint block_size_shift;
swissChilib7ef65d2021-07-17 12:51:52 -070027
28 /// the number to shift 1024 to the left by to get the fragment size
swissChilief829f32021-06-13 20:00:54 -070029 uint fragment_size_shift;
swissChilib7ef65d2021-07-17 12:51:52 -070030
31 /// Number of blocks in one block group
swissChilief829f32021-06-13 20:00:54 -070032 uint blocks_per_block_group;
swissChilib7ef65d2021-07-17 12:51:52 -070033
34 /// Number of fragments in one block group
swissChilief829f32021-06-13 20:00:54 -070035 uint fragments_per_block_group;
swissChilib7ef65d2021-07-17 12:51:52 -070036
37 /// Number of inodse in one block group
swissChilief829f32021-06-13 20:00:54 -070038 uint inodes_per_block_group;
swissChilib7ef65d2021-07-17 12:51:52 -070039
40 /// UNIX time of last mount
swissChilief829f32021-06-13 20:00:54 -070041 uint last_mount_time;
swissChilib7ef65d2021-07-17 12:51:52 -070042
43 /// UNIX time of last write
swissChilief829f32021-06-13 20:00:54 -070044 uint last_write_time;
swissChilib7ef65d2021-07-17 12:51:52 -070045
46 /// Number of mounts since last consistency check
swissChilief829f32021-06-13 20:00:54 -070047 ushort mounts_since_last_fsck;
swissChilib7ef65d2021-07-17 12:51:52 -070048
49 /// Number of mounts allowed between consistency checks
swissChilief829f32021-06-13 20:00:54 -070050 ushort mounts_allowed_before_fsck;
swissChilib7ef65d2021-07-17 12:51:52 -070051
52 /// EXT2 signature, should be 0xef53
swissChilief829f32021-06-13 20:00:54 -070053 ushort signature;
swissChilib7ef65d2021-07-17 12:51:52 -070054
55 /// File system state, see enum ext2_fs_state
swissChilief829f32021-06-13 20:00:54 -070056 ushort state;
swissChilib7ef65d2021-07-17 12:51:52 -070057
58 /// What to do in case of an error, see enum ext2_error_case
swissChilief829f32021-06-13 20:00:54 -070059 ushort error_case;
swissChilib7ef65d2021-07-17 12:51:52 -070060
61 /// Minor portion of version
swissChilief829f32021-06-13 20:00:54 -070062 ushort version_minor;
swissChilib7ef65d2021-07-17 12:51:52 -070063
64 /// UNIX time of last consistency check
swissChilief829f32021-06-13 20:00:54 -070065 uint last_fsck_time;
swissChilib7ef65d2021-07-17 12:51:52 -070066
67 /// Max time between consistency checks
swissChilief829f32021-06-13 20:00:54 -070068 uint fsck_time_interval;
swissChilib7ef65d2021-07-17 12:51:52 -070069
70 /// Operating system ID of creator
swissChilief829f32021-06-13 20:00:54 -070071 uint creator_os_id;
swissChilib7ef65d2021-07-17 12:51:52 -070072
73 /// Major portion of version
swissChilief829f32021-06-13 20:00:54 -070074 uint version_major;
swissChilib7ef65d2021-07-17 12:51:52 -070075
76 /// User ID that can use reserved blocks
swissChilief829f32021-06-13 20:00:54 -070077 ushort reserved_blocks_uid;
swissChilib7ef65d2021-07-17 12:51:52 -070078
79 /// Group ID that can use reserved blocks
swissChilief829f32021-06-13 20:00:54 -070080 ushort reserved_blocks_gid;
81};
82
83enum ext2_fs_state
84{
85 EXT2_STATE_CLEAN = 1,
86 EXT2_STATE_ERRORS = 2,
87};
88
89enum ext2_error_case
90{
91 EXT2_ERROR_IGNORE = 1,
92 EXT2_ERROR_REMOUNT = 2,
93 EXT2_ERROR_KPANIC = 3,
94};
95
96enum ext2_os_id
97{
98 EXT2_OS_LINUX = 0,
99 EXT2_OS_HURD,
100 EXT2_OS_MASIX,
101 EXT2_OS_FREEBSD,
102 EXT2_OS_OTHER_BSD,
103};
104
swissChili9bd74de2021-06-15 20:30:48 -0700105#define EXT2_SIGNATURE 0xef53
106
swissChilib7ef65d2021-07-17 12:51:52 -0700107struct ext2_block_group_descriptor
108{
109 /// Address of block usage bitmap
swissChili4749d022021-07-19 12:33:06 -0700110 uint block_bitmap; // 4
swissChilib7ef65d2021-07-17 12:51:52 -0700111
112 /// Address of inode usage bitmap
swissChili4749d022021-07-19 12:33:06 -0700113 uint inode_bitmap; // 8
swissChilib7ef65d2021-07-17 12:51:52 -0700114
115 /// Starting block address of inode table
swissChili4749d022021-07-19 12:33:06 -0700116 uint inode_table_start_block; // 12
swissChilib7ef65d2021-07-17 12:51:52 -0700117
118 /// Number of unallocated blocks in this group
swissChili4749d022021-07-19 12:33:06 -0700119 ushort unallocated_blocks; // 14
swissChilib7ef65d2021-07-17 12:51:52 -0700120
121 /// Number of unallocated inodes in this group
swissChili4749d022021-07-19 12:33:06 -0700122 ushort unallocated_inodes; // 16
swissChilib7ef65d2021-07-17 12:51:52 -0700123
124 /// Number of directories in this group
swissChili4749d022021-07-19 12:33:06 -0700125 ushort num_dirs; // 18
swissChilib7ef65d2021-07-17 12:51:52 -0700126
swissChili4749d022021-07-19 12:33:06 -0700127 ushort padding; // 20
swissChilib7ef65d2021-07-17 12:51:52 -0700128
swissChili4749d022021-07-19 12:33:06 -0700129 uchar reserved[12]; // 32
swissChilib7ef65d2021-07-17 12:51:52 -0700130};
131
132struct ext2_inode
133{
134 /// The format and permissions of the file, see EXT2_S_*
135 ushort mode;
swissChili4749d022021-07-19 12:33:06 -0700136
swissChilib7ef65d2021-07-17 12:51:52 -0700137 /// The user id of the owner
138 ushort uid;
139
140 /// The lower 32 bits of the file size
141 uint size;
142
143 /// Last time this was accessed in UNIX time
144 uint access_time;
145
146 /// Time this was created in UNIX time
147 uint created_time;
148
149 /// Time this was last modified in UNIX time
150 uint modified_time;
151
152 /// Time this was deleted in UNIX time
153 uint deleted_time;
154
155 /// Owner group id
156 ushort gid;
157
158 /// Reference count for hard links
159 ushort links_count;
160
161 /// Number of 512 byte blocks storing this files data, NOT EXT2 blocks!
162 uint num_blocks;
163
164 /// Flags describing how this file can be accessed
165 uint flags;
166
167 /// First field reserved for the operating system
168 uint os_reserved_1;
169
170 union
171 {
172 /// The blocks of this file
173 uint blocks[15];
174
175 struct
176 {
177 /// The direct blocks
178 uint direct_blocks[12];
179
180 /// The single indirect block
181 uint ind_block;
182
183 /// The double indirect block
184 uint ind2_block;
185
186 /// The triple indirect block
187 uint ind3_block;
188 };
189 };
190
191 /// Used by NFS to version files
192 uint generation;
193
194 /// File attributes, unused
195 uint file_acl;
196
197 /// Directory attributes, unused
198 uint dir_acl;
199
200 /// Location of file fragment, unused
201 uint faddr;
202
203 /// Second field reserved for the operating system
204 uchar os_reserved_2[12];
205};
206
207enum
208{
209 // File types
210 EXT2_S_IFSOCK = 0xc000,
211 EXT2_S_IFLINK = 0xa000,
212 EXT2_S_IFREG = 0x8000,
213 EXT2_S_IFBLK = 0x6000,
214 EXT2_S_IFDIR = 0x4000,
215 EXT2_S_IFCHR = 0x2000,
216 EXT2_S_IFIFO = 0x1000,
217
218 /// Set UID
219 EXT2_S_ISUID = 0x0800,
220 /// Set GUID
221 EXT2_S_ISGID = 0x0400,
222 /// Sticky
223 EXT2_S_ISVTX = 0x0200,
224
225 // Normal UNIX file permissions
226 EXT2_S_IRUSR = 0x0100,
227 EXT2_S_IWUSR = 0x0080,
228 EXT2_S_IXUSR = 0x0040,
229 EXT2_S_IRGRP = 0x0020,
230 EXT2_S_IWGRP = 0x0010,
231 EXT2_S_IXGRP = 0x0008,
232 EXT2_S_IROTH = 0x0004,
233 EXT2_S_IWOTH = 0x0002,
234 EXT2_S_IXOTH = 0x0001,
235};
236
swissChilicbd43632021-07-17 16:19:44 -0700237/// File type flag (used on inode->mode)
238#define EXT2_F_TYPE 0xf000
239
swissChilid98781b2021-07-25 21:04:17 -0700240const extern uchar ext2_s_to_ft[];
241
242/// Converts the file "mode" (inode->mode, EXT2_S_*) to a file type
243/// (EXT2_FT_*).
244#define EXT2_S_TO_FT(s) (ext2_s_to_ft[s >> 12])
245
swissChilib7ef65d2021-07-17 12:51:52 -0700246struct ext2_dirent
247{
248 uint inode;
249 ushort rec_len;
250 uchar name_len;
251 uchar file_type;
252 char name[];
253};
254
swissChili36ed5d72021-07-23 14:56:36 -0700255enum
256{
257 EXT2_FT_UNKNOWN = 0,
258 EXT2_FT_REGULAR_FILE,
259 EXT2_FT_DIR,
260 EXT2_FT_CHRDEV,
261 EXT2_FT_BLKDEV,
262 EXT2_FT_FIFO,
263 EXT2_FT_SOCK,
264 EXT2_FT_SYMLINK,
265};
266
swissChilid98781b2021-07-25 21:04:17 -0700267/// Read a file system block (0-indexed), if necessary multiple disk
268/// blocks will be read automatically
269void ext2_read_block(struct ext2_superblock *sb, void *buffer,
270 uint block);
271void ext2_write_block(struct ext2_superblock *sb, void *buffer,
272 uint block);
swissChilib7ef65d2021-07-17 12:51:52 -0700273
swissChili4418ca52021-06-14 17:36:00 -0700274struct ext2_superblock ext2_read_superblock();
swissChilib7ef65d2021-07-17 12:51:52 -0700275
276void ext2_write_superblock(struct ext2_superblock *sb);
277
swissChilid98781b2021-07-25 21:04:17 -0700278/// Just for fun, corrupt the superblock (obviously don't actually do
279/// this)
swissChilib7ef65d2021-07-17 12:51:52 -0700280void ext2_corrupt_superblock_for_fun();
281
swissChilief829f32021-06-13 20:00:54 -0700282void ext2_mount(struct fs_node *where);
swissChilib7ef65d2021-07-17 12:51:52 -0700283
swissChili9bd74de2021-06-15 20:30:48 -0700284bool ext2_valid_filesystem();
swissChilib7ef65d2021-07-17 12:51:52 -0700285
swissChilid98781b2021-07-25 21:04:17 -0700286/**
287 * @brief Get or set an inode
288 * @param inode Either a pointer to the value to be read (set=false),
289 * or the value to be written (set=true).
290 * @param set True if the inode should be set (written), false
291 * otherwise.
292 */
293bool ext2_get_or_set_inode(struct ext2_superblock *sb, uint number,
294 struct ext2_inode *inode, bool set);
295
296bool ext2_find_inode(struct ext2_superblock *sb, uint number,
297 struct ext2_inode *inode);
298
299bool ext2_set_inode(struct ext2_superblock *sb, uint number,
300 struct ext2_inode *inode);
swissChilib7ef65d2021-07-17 12:51:52 -0700301
302/// Load a block group descriptor for a certain block group
303struct ext2_block_group_descriptor ext2_load_block_group_descriptor(
304 struct ext2_superblock *sb, uint block_group);
305
swissChilid98781b2021-07-25 21:04:17 -0700306/// List the contents of a directory dir. Calls `cb` for each item. If
307/// `dir` is not a directory, returns false. Otherwise returns true.
308/// if cb returns true, ls will continue. Otherwise it will stop.
swissChilib7ef65d2021-07-17 12:51:52 -0700309bool ext2_dir_ls(struct ext2_superblock *sb,
310 struct ext2_inode *dir,
swissChilid98781b2021-07-25 21:04:17 -0700311 bool (*cb)(uint inode,
swissChilib7ef65d2021-07-17 12:51:52 -0700312 const char *name,
swissChilid98781b2021-07-25 21:04:17 -0700313 uint name_len,
swissChilib7ef65d2021-07-17 12:51:52 -0700314 void *data),
315 void *data);
316
317/// Read a data block for the inode, 0 being the first block of the file.
318bool ext2_read_inode_block(struct ext2_superblock *sb,
319 struct ext2_inode *inode,
320 void *buffer,
321 uint block);
swissChilicbd43632021-07-17 16:19:44 -0700322
swissChili36ed5d72021-07-23 14:56:36 -0700323/// Write a data block for the inode, 0 being the first block of the file.
324bool ext2_write_inode_block(struct ext2_superblock *sb, struct ext2_inode *dir,
325 void *buffer, uint block);
326
swissChili4749d022021-07-19 12:33:06 -0700327ssize_t ext2_read_inode(struct ext2_superblock *sb, struct ext2_inode *inode, void *buffer, ssize_t size);
328
329/**
330 * @brief Set a block in a bitmap
331 * @param bitmap_block The first block of the bitmap, not necessarily the block
332 * that this specific bit is in.
333 * @param index The bit to check, starting at 0
334 * @returns The value of the bit
335 */
336bool ext2_check_in_bitmap(struct ext2_superblock *sb, uint bitmap_block,
337 uint index);
338
339/**
340 * @brief Set a block in a bitmap
341 * @param bitmap_block The first block of the bitmap, not necessarily the block
342 * that this specific bit is in.
343 * @param index The bit to set, starting at 0
344 * @param value The value of the bit, 0 for 0, non-0 for 1
345 */
346void ext2_set_in_bitmap(struct ext2_superblock *sb, uint bitmap_block,
347 uint index, bool value);
348
349/**
350 * @brief Find the first zero bit in a bitset
351 * @param bitmap_block The first block of the bitmap
352 * @param num_blocks The number of blocks in the bitmap, or ~0 for no limit
353 * (UNSAFE).
354 * @param start_at The first bit to search from, useful if you want to ignore
355 * the first reserved inodes.
356 * @returns The index of the first zero bit, or -1 if there is none
357 */
358uint ext2_first_zero_bit(struct ext2_superblock *sb, uint bitmap_block,
359 uint num_blocks, uint start_at);
360
swissChili36ed5d72021-07-23 14:56:36 -0700361/**
362 * Find the first free inode number.
363 * @returns The inode if it was found, 0 if there are no free inodes.
364 */
swissChili4749d022021-07-19 12:33:06 -0700365uint ext2_first_free_inode(struct ext2_superblock *sb);
swissChili36ed5d72021-07-23 14:56:36 -0700366
367void ext2_insert_into_dir(struct ext2_superblock *sb, struct ext2_inode *dir,
368 char *name, uint name_len, uint inode, uchar type);
swissChilid98781b2021-07-25 21:04:17 -0700369
370/**
371 * Creates a hard link
372 * @param dir Directory to create the hard link in
373 * @param name Name of the link to create
374 * @param name_len length of name, not including (optional) NULL byte
375 * @param inode Inode number of link target
376 */
377bool ext2_hard_link(struct ext2_superblock *sb, struct ext2_inode *dir,
378 char *name, uint name_len, uint inode);
379
380/**
381 * @brief Does a directory contain a certain entry?
382 * @param sb Superblock
383 * @param dir The directory to search in
384 * @param name The name of the entry to look for
385 * @param len The length of the name, not including the optional NULL byte
386 * @returns True if the entry is found, false if not, or if something
387 * goes wrong (ie: dir is not a directory)
388 */
389bool ext2_dir_contains(struct ext2_superblock *sb, struct ext2_inode *dir,
390 char *name, uint len);
391
392/**
393 * @brief Find an entry in a directory
394 * @param dir Directory to search in
395 * @param name Name of file
396 * @param name_len Length of name, not including (optional) NULL byte.
397 * @returns 0 if no entry could be found, otherwise inode number for
398 * that entry
399 */
400uint ext2_dir_find(struct ext2_superblock *sb, struct ext2_inode *dir,
401 char *name, uint name_len);