Two fixes
[tfsprogs.git] / inode.c
blob94d5b2fe386a7effa553f0fe1fc301ba2bd67492
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 printf("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 memset(inode->i_data, 0, TFS_N_BLOCKS * sizeof(uint32_t *));
37 if (!inode->i_data) {
38 printf("malloc for inode data failed!\n");
39 free(inode);
40 return NULL;
44 return inode;
49 * release all the stuff related to the inode
51 int tfs_release_inode(struct tfs_sb_info *sbi, struct inode *inode)
53 int inr = inode->i_ino;
54 int index = 0;
55 int block;
57 if (!inode) {
58 printf("ERROR: trying to free a NULL inode!\n");
59 return -1;
62 TFS_DEBUG("trying to release inode: %d\n", inr);
64 if (tfs_free_inode(sbi, inr) == -1) {
65 printf("ERROR: trying to free inode %d failed!\n", inr);
66 return -1;
69 while ((block = tfs_bmap(inode, index++)))
70 tfs_free_block(sbi, block);
72 free_inode(inode);
76 struct inode * tfs_new_inode(struct tfs_sb_info *sbi, int mode)
78 struct inode *inode;
79 int inr;
81 inode = new_inode(mode);
82 if (!inode)
83 return NULL;
84 /*
85 * allocate it start from TFS_ROOT_INODE, so only the first one
86 * will get it:)
87 */
88 inr = tfs_alloc_inode(sbi, TFS_ROOT_INODE);
89 if (inr == -1) {
90 free(inode);
91 return NULL;
94 inode->i_ino = inr;
96 return inode;
99 struct inode * tfs_root_init(struct tfs_sb_info *sbi)
101 struct inode *inode;
103 inode = tfs_new_inode(sbi, TFS_DIR);
104 if (inode->i_ino != TFS_ROOT_INODE) {
105 TFS_DEBUG("root init error!\n");
106 free_inode(inode);
107 inode = NULL;
110 return inode;
114 static void tfs_fill_inode(struct inode *inode, struct tfs_inode *tinode)
116 //inode->i_mode = get_mode(tinode->i_mode);
117 inode->i_mode = tinode->i_mode;
118 inode->i_size = tinode->i_size;
119 inode->i_atime = tinode->i_atime;
120 inode->i_ctime = tinode->i_ctime;
121 inode->i_mtime = tinode->i_mtime;
122 inode->i_dtime = tinode->i_dtime;
123 inode->i_flags = tinode->i_flags;
125 memcpy(inode->i_data, tinode->i_block, TFS_N_BLOCKS * sizeof(uint32_t *));
128 static int tfs_read_inode(struct tfs_sb_info *sbi, struct tfs_inode *tinode, int inr)
130 uint32_t inode_block;
131 struct cache_struct *cs;
133 inode_block = sbi->s_inode_table + (inr - 1) / TFS_INODES_PER_BLOCK(sbi);
134 cs = get_cache_block(sbi, inode_block);
135 if (!cs)
136 return -1;
138 memcpy(tinode, cs->data + ((inr - 1) % TFS_INODES_PER_BLOCK(sbi)) * sizeof(*tinode), sizeof(*tinode));
140 return 0;
143 struct inode * tfs_iget_by_inr(struct tfs_sb_info *sbi, int inr)
145 struct inode *inode;
146 struct tfs_inode tinode;
148 if (tfs_read_inode(sbi, &tinode, inr) == -1) {
149 printf("ERROR: read disk inode error!\n");
150 return NULL;
153 inode = new_inode(0);
154 if (inode) {
155 tfs_fill_inode(inode, &tinode);
156 inode->i_ino = inr;
159 return inode;
162 struct inode *tfs_iget_root(struct tfs_sb_info *sbi)
164 return tfs_iget_by_inr(sbi, TFS_ROOT_INODE);
167 struct inode *tfs_iget(struct tfs_sb_info * sbi, char *dname, struct inode *dir)
169 struct tfs_dir_entry *de;
171 if (!tfs_find_entry(sbi, dname, dir, &de))
172 return NULL;
174 return tfs_iget_by_inr(sbi, de->d_inode);
177 static void tfs_write_inode(struct tfs_inode *tinode, struct inode *inode)
179 tinode->i_mode = inode->i_mode;
180 tinode->i_size = inode->i_size;
181 tinode->i_atime = inode->i_atime;
182 tinode->i_ctime = inode->i_ctime;
183 tinode->i_mtime = inode->i_mtime;
184 tinode->i_dtime = inode->i_dtime;
185 tinode->i_flags = inode->i_flags;
187 memcpy(tinode->i_block, inode->i_data, TFS_N_BLOCKS * sizeof(uint32_t *));
188 tinode->i_reserved[0] = 0;
192 int tfs_iwrite(struct tfs_sb_info *sbi, struct inode *inode)
194 struct cache_struct *cs;
195 struct tfs_inode *tinode;
196 uint32_t inode_block;
197 int res = 0;
199 inode_block = sbi->s_inode_table + (inode->i_ino - 1) / TFS_INODES_PER_BLOCK(sbi);
200 cs = get_cache_block(sbi, inode_block);
201 if (!cs)
202 return -1;
203 tinode = (struct tfs_inode *)cs->data + ((inode->i_ino - 1) % TFS_INODES_PER_BLOCK(sbi));
204 tfs_write_inode(tinode, inode);
205 res = tfs_bwrite(sbi, inode_block, cs->data);
207 return -1;
210 uint32_t tfs_bmap(struct inode *inode, int index)
212 if (index >= TFS_N_BLOCKS) {
213 printf("File too big!\n");
214 return 0;
217 return inode->i_data[index];
222 struct inode * tfs_namei(struct tfs_sb_info *sbi, const char *name, uint32_t flag)
224 struct inode *inode;
225 struct inode *parent;
226 char part[TFS_NAME_LEN + 1];
227 char *p;
229 if (*name == '/') {
230 inode = tfs_iget_root(sbi);
231 while (*name == '/')
232 name++;
233 } else {
234 inode = this_dir->dd_dir->inode;
237 parent = inode;
239 while (*name) {
240 p = part;
241 while (*name && *name != '/') {
242 if (p >= part + TFS_NAME_LEN) {
243 printf("ERROR: file name to long!\n");
244 return NULL;
246 *p++ = *name++;
248 *p = '\0';
249 while (*name && *name == '/')
250 name++;
251 if (!*name && (flag & LOOKUP_PARENT))
252 return parent;
253 inode = tfs_iget(sbi, part, parent);
254 if (!inode)
255 break;
257 if (parent != this_dir->dd_dir->inode)
258 free_inode(parent);
259 parent = inode;
260 if (!*name)
261 break;
264 if (!inode && flag & LOOKUP_CREATE) {
265 inode = __mknod(sbi, parent, part, TFS_FILE);
266 tfs_iwrite(sbi, inode);
269 return inode;
272 static const char *__strrchr(const char *s, int c)
274 const char *end = s + strlen(s) - 1;
275 while (*end != c && end >= s)
276 end--;
277 if (end < s)
278 return NULL;
279 return end;
282 const char *get_base_name(const char *path_org)
284 char *p;
285 char *path = strdup(path_org);
287 p = strrchr(path, '/');
288 if (!p) {
289 free(path);
290 return path_org;
292 /* the /linux/hello/ case */
293 if (*(p + 1) == 0) {
294 *p = 0;
295 p--;
296 while (*p != '/' && p >= path) {
297 *p = 0;
298 p--;
300 if (p < path)
301 return NULL;
304 return p + 1;
307 struct inode * __mknod(struct tfs_sb_info *sbi, struct inode *dir, const char *filename, int mode)
309 struct inode *inode;
310 struct tfs_dir_entry *de;
311 struct cache_struct *cs;
312 int dirty = 0;
314 if (cs = tfs_find_entry(sbi, filename, dir, &de)) {
315 printf("ERROR: %s exist!\n", filename);
316 return NULL;
319 inode = tfs_new_inode(sbi, mode);
320 if (!inode)
321 return NULL;
322 inode->i_mtime = inode->i_atime = current_time;
323 tfs_iwrite(sbi, inode);
325 if (tfs_add_entry(sbi, dir, filename, inode->i_ino, &dirty) == -1) {
326 TFS_DEBUG("trying to add a new entry: %s faild!\n", filename);
327 free_inode(dir);
328 free_inode(inode);
329 return NULL;
331 if (dirty)
332 tfs_iwrite(sbi, dir);
334 return inode;
337 struct inode * tfs_mknod(struct tfs_sb_info *sbi, const char *filename, int mode, struct inode **parent_dir)
339 struct inode *dir;
340 struct inode *inode;
341 const char *base_name = get_base_name(filename);
343 dir = tfs_namei(sbi, filename, LOOKUP_PARENT);
344 if (!dir) {
345 printf("ERROR: path not exist!\n");
346 return NULL;
349 inode = __mknod(sbi, dir, base_name, mode);
350 if (parent_dir) {
351 *parent_dir = dir;
352 } else {
353 if (this_dir->dd_dir->inode != dir)
354 free_inode(dir);
357 return inode;
361 #if 0 /* the debug part */
362 int main(int argc, char *argv[])
365 #endif