-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfile.h
256 lines (220 loc) · 7.88 KB
/
file.h
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
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
/* SPDX-License-Identifier: MIT
*
* SPDX-FileCopyrightText: Copyright (c) 2024 Ian Hangartner <icrashstuff at outlook dot com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef RAMFS_FILE_H
#define RAMFS_FILE_H
#include <sys/stat.h>
#include <sys/types.h>
#include <time.h>
#ifndef INODE_BUF_SIZE_ALIGN_HIGH
#define INODE_BUF_SIZE_ALIGN_HIGH 4096
#endif
/* This overrides INODE_BUF_SIZE_ALIGN_HIGH when req_size is less than INODE_BUF_SIZE_ALIGN_HIGH */
#ifndef INODE_BUF_SIZE_ALIGN_MID
#define INODE_BUF_SIZE_ALIGN_MID 256
#endif
/* This overrides INODE_BUF_SIZE_ALIGN_MID when req_size is less than INODE_BUF_SIZE_ALIGN_MID */
#ifndef INODE_BUF_SIZE_ALIGN_LOW
#define INODE_BUF_SIZE_ALIGN_LOW 64
#endif
/* When the buffer is below this percentage, shrink the buffer */
#ifndef INODE_BUF_SIZE_SHRINK_PERCENTAGE
#define INODE_BUF_SIZE_SHRINK_PERCENTAGE 50
#endif
#if INODE_BUF_SIZE_ALIGN_MID > INODE_BUF_SIZE_ALIGN_HIGH
#error "INODE_BUF_SIZE_ALIGN_MID cannot be greater than INODE_BUF_SIZE_ALIGN_HIGH"
#endif
#if INODE_BUF_SIZE_ALIGN_LOW > INODE_BUF_SIZE_ALIGN_MID
#error "INODE_BUF_SIZE_ALIGN_LOW cannot be greater than INODE_BUF_SIZE_ALIGN_MID"
#endif
struct inode_t
{
size_t inode_num;
size_t buf_size;
size_t file_size;
char* buf;
/**
* Access time
* Because this is a ramfs we will update this every time
* the contents of buf are modified, read, or created
*
* see strictatime and relatime fs mount options for future ideas
*/
struct timespec atime;
/** Metadata Modification time (also includes non-zero calls to write) */
struct timespec ctime;
/** Content Modification time */
struct timespec mtime;
/** inode_t creation time (should not be changed) */
struct timespec btime;
uid_t uid;
gid_t gid;
mode_t mode;
/**
* Number of hard links to inode, in the case of directories there is the . directory which increases the value to 1
* If nlink and refs both hit 0, then delete (this will be important when and if hardlinks are implemented)
*/
nlink_t nlink;
/**
* Number of unreleased open() calls to the inode
* If nlink and refs both hit 0, then the inode can be deleted (this will be important when and if hardlinks are implemented)
*/
size_t nrefs;
};
struct lookup_t
{
char* basename;
size_t name_buf_size;
struct lookup_t* parent;
struct lookup_t* child;
struct lookup_t* prev;
struct lookup_t* next;
/** inode_ptr must ALWAYS be a valid pointer */
struct inode_t* inode_ptr;
};
struct filesystem_t
{
struct lookup_t* root_lookup;
};
/**
* Values that control which time fields will be updated by inode_update_times
*/
enum inode_time_update_level_t
{
INODE_TIME_LEVEL_ACCESS = 0,
INODE_TIME_LEVEL_MODIFY_METADATA = 1,
INODE_TIME_LEVEL_MODIFY_CONTENTS = 2,
INODE_TIME_LEVEL_CREATION = 3,
};
/**
* Helper function to update appropriate inode times
*
* Returns 1 on success and 0 on failure
*/
int inode_update_times(struct inode_t* inode, enum inode_time_update_level_t level);
/**
* Finds first lookup with name matching path limited to name_len if it were as long as name_len in first_lookup structure
*
* Returns 1 on success and 0 on failure
*/
int find_lookupn(const char* caller, const char* path, size_t name_len, struct lookup_t* first_lookup, struct lookup_t** found_lookup);
/**
* Finds first lookup with name matching path in first_lookup structure
*
* Returns 1 on success and 0 on failure
*/
int find_lookup(const char* caller, const char* path, struct lookup_t* first_lookup, struct lookup_t** found_lookup);
/**
* Convenience function that calls find_lookupn and sets *found_inode to inode_ptr
*
* Returns 1 on success and 0 on failure
*/
int find_inoden(const char* caller, const char* path, size_t name_len, struct lookup_t* first_lookup, struct inode_t** found_inode);
/**
* Convenience function that calls find_lookup and sets *found_inode to inode_ptr
*
* Returns 1 on success and 0 on failure
*/
int find_inode(const char* caller, const char* path, struct lookup_t* first_lookup, struct inode_t** found_inode);
/**
* Appends new_lookup to the end of the current level list of first_lookup
*
* Returns 1 on success and 0 on failure
*/
int lookup_append_lookup_as_next(struct lookup_t* first_lookup, struct lookup_t* new_lookup);
/**
* Appends new_lookup to the end of the child list of parent_file
*
* Returns 1 on success and 0 on failure
*/
int lookup_append_lookup_as_child(struct lookup_t* parent_lookup, struct lookup_t* new_lookup);
/**
* Removes a lookup from the a lookup_t linked list
*
* Returns 1 on success and 0 on failure
*/
int lookup_pluck_lookup(struct lookup_t* lookup);
/**
* Frees a lookup, its children, and all following lookup_t->next and lookup_t->child entries
*
* Also calls inode_free_inode() on the underlying inode
*
* Returns 1 on success and 0 on failure
*/
int lookup_free_lookups(struct lookup_t* first_lookup);
/**
* Convenience function that plucks and then frees lookup in a way that is least likely to cause problems
*
* Returns 1 on success and 0 on failure
*/
int lookup_pluck_and_free_lookup(struct lookup_t* lookup);
/**
* Frees a lookup, its children, and all following lookup_t->next and lookup_t->child entries
*
* Also calls inode_free_inode_no_refs() on the underlying inode after zeroing nrefs and decrementing nlink
*
* Returns 1 on success and 0 on failure
*/
int lookup_free_lookups_no_refs(struct lookup_t* first_lookup);
/**
* Frees an inode if nlink and nrefs are 0
*
* Returns 1 on success and 0 if inode is null
*/
int inode_free_inode(struct inode_t* inode);
/**
* Resizes the buffer to at least req_size and changes the file_size to req_size
*
* Returns 1 on success and 0 on failure
*/
int inode_resize_buf(const char* caller, struct inode_t* inode, size_t req_size);
/**
* Renames a lookup, this may involve reallocating lookup_t->name if the new name is longer
*
* Returns 1 on success and 0 on failure
*/
int lookup_rename(struct lookup_t* lookup, const char* new_name);
/**
* Creates a lookup_t object and assigns the pointer at *lookup_ptr
*
* Returns 1 on success and 0 on failure
*/
int lookup_create(const char* name, struct lookup_t** lookup_ptr);
/**
* Creates a lookup_t object with inode_ptr from src_lookup at *lookup_ptr
*
* Increments inode_ptr->nlink
*
* Returns 1 on success and 0 on failure
*/
int lookup_clone_lookup(const char* name, struct lookup_t* src_lookup, struct lookup_t** lookup_ptr);
/**
* Prints a tree(1)-like view of a lookup_t structure
*/
void lookup_print_tree(struct lookup_t* lookup, long int level);
/**
* This is only meant to be used when initializing the filesystem
*
* Warning: This function is not thread safe as it relies on a static variable
*/
void lookup_create_blank_nodes_for_stress(struct lookup_t* _root_lookup, uint num_dirs, uint num_files);
#endif // RAMFS_FILE_H