Add tfs remove part
[thunix.git] / fs / tfs / inode.c
blob68b72c6fdbff47e853f50e2346c917d96ab46f7b
1 #include <stdio.h>
2 #include <string.h>
3 #include <malloc.h>
5 #include "tfs.h"
6 #include "cache.h"
7 #include "dirent.h"
9 #define current_time 0
12 void free_inode(struct inode *inode)
14 if(inode->i_data)
15 free(inode->i_data);
16 free(inode);
19 struct inode *new_inode(int mode)
21 struct inode *inode;
23 inode = malloc(sizeof(*inode));
24 if (!inode) {
25 printk("malloc for new inode failed!\n");
26 return NULL;
28 memset(inode, 0, sizeof(*inode));
29 inode->i_mode = mode;
31 inode->i_atime = current_time;
32 inode->i_ctime = current_time;
33 inode->i_mtime = current_time;
35 inode->i_data = malloc(TFS_N_BLOCKS * sizeof(uint32_t *));
36 if (!inode->i_data) {
37 printk("malloc for inode data failed!\n");
38 free(inode);
39 return NULL;
43 return inode;
48 * release all the stuff related to the inode
50 int tfs_release_inode(struct tfs_sb_info *sbi, struct inode *inode)
52 int inr = inode->i_ino;
53 int index = 0;
54 int block;
56 if (!inode) {
57 printk("ERROR: trying to free a NULL inode!\n");
58 return -1;
61 TFS_DEBUG("trying to release inode: %d\n", inr);
63 if (tfs_free_inode(sbi, inr) == -1) {
64 printk("ERROR: trying to free inode %d failed!\n", inr);
65 return -1;
68 while ((block = tfs_bmap(inode, index++)))
69 tfs_free_block(sbi, block);
71 free_inode(inode);
75 struct inode * tfs_new_inode(struct tfs_sb_info *sbi, int mode)
77 struct inode *inode;
78 int inr;
80 inode = new_inode(mode);
81 if (!inode)
82 return NULL;
83 /*
84 * allocate it start from TFS_ROOT_INODE, so only the first one
85 * will get it:)
86 */
87 inr = tfs_alloc_inode(sbi, TFS_ROOT_INODE);
88 if (inr == -1) {
89 free(inode);
90 return NULL;
93 inode->i_ino = inr;
95 return inode;
98 struct inode * tfs_root_init(struct tfs_sb_info *sbi)
100 struct inode *inode;
102 inode = tfs_new_inode(sbi, TFS_DIR);
103 if (inode->i_ino != TFS_ROOT_INODE) {
104 TFS_DEBUG("root init error!\n");
105 free_inode(inode);
106 inode = NULL;
109 return inode;
113 static void tfs_fill_inode(struct inode *inode, struct tfs_inode *tinode)
115 //inode->i_mode = get_mode(tinode->i_mode);
116 inode->i_mode = tinode->i_mode;
117 inode->i_size = tinode->i_size;
118 inode->i_atime = tinode->i_atime;
119 inode->i_ctime = tinode->i_ctime;
120 inode->i_mtime = tinode->i_mtime;
121 inode->i_dtime = tinode->i_dtime;
122 inode->i_flags = tinode->i_flags;
124 memcpy(inode->i_data, tinode->i_block, TFS_N_BLOCKS * sizeof(uint32_t *));
127 static int tfs_read_inode(struct tfs_sb_info *sbi, struct tfs_inode *tinode, int inr)
129 uint32_t inode_block;
130 struct cache_struct *cs;
132 inode_block = sbi->s_inode_table + (inr - 1) / TFS_INODES_PER_BLOCK(sbi);
133 cs = get_cache_block(sbi, inode_block);
134 if (!cs)
135 return -1;
137 memcpy(tinode, cs->data + ((inr - 1) % TFS_INODES_PER_BLOCK(sbi)) * sizeof(*tinode), sizeof(*tinode));
139 return 0;
142 struct inode * tfs_iget_by_inr(struct tfs_sb_info *sbi, int inr)
144 struct inode *inode;
145 struct tfs_inode tinode;
147 if (tfs_read_inode(sbi, &tinode, inr) == -1) {
148 printk("ERROR: read disk inode error!\n");
149 return NULL;
152 inode = new_inode(0);
153 if (inode) {
154 tfs_fill_inode(inode, &tinode);
155 inode->i_ino = inr;
158 return inode;
161 struct inode *tfs_iget_root(struct tfs_sb_info *sbi)
163 return tfs_iget_by_inr(sbi, TFS_ROOT_INODE);
166 struct inode *tfs_iget(struct tfs_sb_info * sbi, char *dname, struct inode *dir)
168 struct tfs_dir_entry *de;
170 if (!tfs_find_entry(sbi, dname, dir, &de))
171 return NULL;
173 return tfs_iget_by_inr(sbi, de->d_inode);
176 static void tfs_write_inode(struct tfs_inode *tinode, struct inode *inode)
178 tinode->i_mode = inode->i_mode;
179 tinode->i_size = inode->i_size;
180 tinode->i_atime = inode->i_atime;
181 tinode->i_ctime = inode->i_ctime;
182 tinode->i_mtime = inode->i_mtime;
183 tinode->i_dtime = inode->i_dtime;
184 tinode->i_flags = inode->i_flags;
186 memcpy(tinode->i_block, inode->i_data, TFS_N_BLOCKS * sizeof(uint32_t *));
187 tinode->i_reserved[0] = 0;
191 int tfs_iwrite(struct tfs_sb_info *sbi, struct inode *inode)
193 struct cache_struct *cs;
194 struct tfs_inode *tinode;
195 uint32_t inode_block;
196 int res = 0;
198 inode_block = sbi->s_inode_table + (inode->i_ino - 1) / TFS_INODES_PER_BLOCK(sbi);
199 cs = get_cache_block(sbi, inode_block);
200 if (!cs)
201 return -1;
202 tinode = (struct tfs_inode *)cs->data + ((inode->i_ino - 1) % TFS_INODES_PER_BLOCK(sbi));
203 tfs_write_inode(tinode, inode);
204 tfs_bwrite(sbi, inode_block, cs->data);
206 return -1;
209 uint32_t tfs_bmap(struct inode *inode, int index)
211 if (index >= TFS_N_BLOCKS) {
212 printk("File too big!\n");
213 return 0;
216 return inode->i_data[index];
221 struct inode * tfs_namei(struct tfs_sb_info *sbi, const char *name, uint32_t flag)
223 struct inode *inode;
224 struct inode *parent;
225 char part[TFS_NAME_LEN + 1];
226 char *p;
228 if (*name == '/') {
229 inode = tfs_iget_root(sbi);
230 while (*name == '/')
231 name++;
232 } else {
233 inode = this_dir->dd_dir->inode;
236 parent = inode;
238 while (*name) {
239 p = part;
240 while (*name && *name != '/') {
241 if (p >= part + TFS_NAME_LEN) {
242 printk("ERROR: file name to long!\n");
243 return NULL;
245 *p++ = *name++;
247 *p = '\0';
248 while (*name && *name == '/')
249 name++;
250 if (!*name && (flag & LOOKUP_PARENT))
251 return parent;
252 inode = tfs_iget(sbi, part, parent);
253 if (!inode)
254 break;
256 if (parent != this_dir->dd_dir->inode)
257 free_inode(parent);
258 parent = inode;
259 if (!*name)
260 break;
263 if (!inode && flag & LOOKUP_CREATE) {
264 inode = __mknod(sbi, parent, part, TFS_FILE);
265 tfs_iwrite(sbi, inode);
268 return inode;
271 static const char *__strrchr(const char *s, int c)
273 const char *end = s + strlen(s) - 1;
274 while (*end != c && end >= s)
275 end--;
276 if (end < s)
277 return NULL;
278 return end;
281 const char *get_base_name(const char *path_org)
283 char *p;
284 char *path = strdup(path_org);
286 p = strrchr(path, '/');
287 if (!p) {
288 free(path);
289 return path_org;
291 /* the /linux/hello/ case */
292 if (*(p + 1) == 0) {
293 *p = 0;
294 p--;
295 while (*p != '/' && p >= path) {
296 *p = 0;
297 p--;
299 if (p < path)
300 return NULL;
303 return p + 1;
306 struct inode * __mknod(struct tfs_sb_info *sbi, struct inode *dir, const char *filename, int mode)
308 struct inode *inode;
309 struct tfs_dir_entry *de;
310 struct cache_struct *cs;
311 int dirty = 0;
313 if (cs = tfs_find_entry(sbi, filename, dir, &de)) {
314 printk("ERROR: %s exist!\n", filename);
315 return NULL;
318 inode = tfs_new_inode(sbi, mode);
319 if (!inode)
320 return NULL;
321 inode->i_mtime = inode->i_atime = current_time;
322 tfs_iwrite(sbi, inode);
324 if (tfs_add_entry(sbi, dir, filename, inode->i_ino, &dirty) == -1) {
325 TFS_DEBUG("trying to add a new entry: %s faild!\n", filename);
326 free_inode(dir);
327 free_inode(inode);
328 return NULL;
330 if (dirty)
331 tfs_iwrite(sbi, dir);
333 return inode;
336 struct inode * tfs_mknod(struct tfs_sb_info *sbi, const char *filename, int mode, struct inode **parent_dir)
338 struct inode *dir;
339 struct inode *inode;
340 const char *base_name = get_base_name(filename);
342 dir = tfs_namei(sbi, filename, LOOKUP_PARENT);
343 if (!dir) {
344 printk("ERROR: path not exist!\n");
345 return NULL;
348 inode = __mknod(sbi, dir, base_name, mode);
349 if (parent_dir) {
350 *parent_dir = dir;
351 } else {
352 if (this_dir->dd_dir->inode != dir)
353 free_inode(dir);
356 return inode;
360 #if 0 /* the debug part */
361 int main(int argc, char *argv[])
364 #endif