add file read/write stuff
[tfsprogs.git] / inode.c
blob6815da73678bd06742761d7c1ccda399c389d60a
1 #include <stdio.h>
2 #include <string.h>
3 #include <malloc.h>
5 #include "tfs.h"
6 #include "cache.h"
8 #define current_time 0
11 void free_inode(struct inode *inode)
13 if(inode->i_data)
14 free(inode->i_data);
15 free(inode);
18 struct inode *new_inode(int mode)
20 struct inode *inode;
22 inode = malloc(sizeof(*inode));
23 if (!inode) {
24 printf("malloc for new inode failed!\n");
25 return NULL;
27 memset(inode, 0, sizeof(*inode));
28 inode->i_mode = mode;
30 inode->i_atime = current_time;
31 inode->i_ctime = current_time;
32 inode->i_mtime = current_time;
34 inode->i_data = malloc(TFS_N_BLOCKS * sizeof(uint32_t *));
35 if (!inode->i_data) {
36 printf("malloc for inode data failed!\n");
37 free(inode);
38 return NULL;
42 return inode;
47 * release all the stuff related to the inode
49 int tfs_release_inode(struct tfs_sb_info *sbi, struct inode *inode)
51 int inr = inode->i_ino;
53 if (!inode) {
54 printf("ERROR: trying to free a NULL inode!\n");
55 return -1;
58 TFS_DEBUG("trying to release inode: %d\n", inr);
60 if (tfs_free_inode(sbi, inr) == -1) {
61 printf("ERROR: trying to free inode %d failed!\n", inr);
62 return -1;
65 free_inode(inode);
69 struct inode * tfs_new_inode(struct tfs_sb_info *sbi, int mode)
71 struct inode *inode;
72 int inr;
74 inode = new_inode(mode);
75 if (!inode)
76 return NULL;
77 /*
78 * allocate it start from TFS_ROOT_INODE, so only the first one
79 * will get it:)
80 */
81 inr = tfs_alloc_inode(sbi, TFS_ROOT_INODE);
82 if (inr == -1) {
83 free(inode);
84 return NULL;
87 inode->i_ino = inr;
89 return inode;
92 struct inode * tfs_root_init(struct tfs_sb_info *sbi)
94 struct inode *inode;
96 inode = tfs_new_inode(sbi, TFS_DIR);
97 if (inode->i_ino != TFS_ROOT_INODE) {
98 TFS_DEBUG("root init error!\n");
99 free_inode(inode);
100 inode = NULL;
103 return inode;
107 static void tfs_fill_inode(struct inode *inode, struct tfs_inode *tinode)
109 //inode->i_mode = get_mode(tinode->i_mode);
110 inode->i_mode = tinode->i_mode;
111 inode->i_size = tinode->i_size;
112 inode->i_atime = tinode->i_atime;
113 inode->i_ctime = tinode->i_ctime;
114 inode->i_mtime = tinode->i_mtime;
115 inode->i_dtime = tinode->i_dtime;
116 inode->i_flags = tinode->i_flags;
118 memcpy(inode->i_data, tinode->i_block, TFS_N_BLOCKS * sizeof(uint32_t *));
121 static int tfs_read_inode(struct tfs_sb_info *sbi, struct tfs_inode *tinode, int inr)
123 uint32_t inode_block;
124 struct cache_struct *cs;
126 inode_block = sbi->s_inode_table + (inr - 1) / TFS_INODES_PER_BLOCK(sbi);
127 cs = get_cache_block(sbi, inode_block);
128 if (!cs)
129 return -1;
131 memcpy(tinode, cs->data + ((inr - 1) % TFS_INODES_PER_BLOCK(sbi)) * sizeof(*tinode), sizeof(*tinode));
133 return 0;
136 struct inode * tfs_iget_by_inr(struct tfs_sb_info *sbi, int inr)
138 struct inode *inode;
139 struct tfs_inode tinode;
141 if (tfs_read_inode(sbi, &tinode, inr) == -1) {
142 printf("ERROR: read disk inode error!\n");
143 return NULL;
146 inode = new_inode(0);
147 if (inode) {
148 tfs_fill_inode(inode, &tinode);
149 inode->i_ino = inr;
152 return inode;
155 struct inode *tfs_iget_root(struct tfs_sb_info *sbi)
157 return tfs_iget_by_inr(sbi, TFS_ROOT_INODE);
160 struct inode *tfs_iget(struct tfs_sb_info * sbi, char *dname, struct inode *dir)
162 struct tfs_dir_entry *de;
164 de = tfs_find_entry(sbi, dname, dir);
165 if (!de)
166 return NULL;
168 return tfs_iget_by_inr(sbi, de->d_inode);
171 static void tfs_write_inode(struct tfs_inode *tinode, struct inode *inode)
173 tinode->i_mode = inode->i_mode;
174 tinode->i_size = inode->i_size;
175 tinode->i_atime = inode->i_atime;
176 tinode->i_ctime = inode->i_ctime;
177 tinode->i_mtime = inode->i_mtime;
178 tinode->i_dtime = inode->i_dtime;
179 tinode->i_flags = inode->i_flags;
181 memcpy(tinode->i_block, inode->i_data, TFS_N_BLOCKS * sizeof(uint32_t *));
182 tinode->i_reserved[0] = 0;
186 int tfs_iwrite(struct tfs_sb_info *sbi, struct inode *inode)
188 struct cache_struct *cs;
189 struct tfs_inode *tinode;
190 uint32_t inode_block;
191 int res = 0;
193 inode_block = sbi->s_inode_table + (inode->i_ino - 1) / TFS_INODES_PER_BLOCK(sbi);
194 cs = get_cache_block(sbi, inode_block);
195 if (!cs)
196 return -1;
197 tinode = (struct tfs_inode *)cs->data + ((inode->i_ino - 1) % TFS_INODES_PER_BLOCK(sbi));
198 tfs_write_inode(tinode, inode);
199 res = tfs_bwrite(sbi, inode_block, cs->data);
200 cs->outdate = 1;
202 return -1;
206 struct inode * tfs_namei(struct tfs_sb_info *sbi, const char *name, uint32_t flag)
208 struct inode *inode;
209 struct inode *parent;
210 char part[TFS_NAME_LEN + 1];
211 char *p;
213 if (*name == '/') {
214 inode = tfs_iget_root(sbi);
215 while (*name == '/')
216 name++;
217 } else {
218 printf("ERROR: relative path searching is not supported for now!\n");
219 return NULL;
221 parent = inode;
223 while (*name) {
224 p = part;
225 while (*name && *name != '/') {
226 if (p >= part + TFS_NAME_LEN) {
227 printf("ERROR: file name to long!\n");
228 return NULL;
230 *p++ = *name++;
232 *p = '\0';
233 while (*name && *name == '/')
234 name++;
235 if (!*name && (flag & LOOKUP_PARENT))
236 return parent;
237 inode = tfs_iget(sbi, part, parent);
238 if (!inode)
239 return NULL;
241 free_inode(parent);
242 parent = inode;
243 if (!*name)
244 break;
247 return inode;
250 static const char *__strrchr(const char *s, int c)
252 const char *end = s + strlen(s) - 1;
253 while (*end != c && end >= s)
254 end--;
255 if (end < s)
256 return NULL;
257 return end;
260 static char *get_base_name(const char *path_org)
262 char *p;
263 char *path = strdup(path_org);
265 p = strrchr(path, '/');
266 if (!p)
267 return NULL;
268 /* the /linux/hello/ case */
269 if (*(p + 1) == 0) {
270 *p = 0;
271 p--;
272 while (*p != '/' && p >= path) {
273 *p = 0;
274 p--;
276 if (p < path)
277 return NULL;
280 return p;
283 struct inode * tfs_mknod(struct tfs_sb_info *sbi, const char *path, int mode, struct inode **parent_dir)
285 struct inode *dir;
286 struct inode *inode;
287 const char *filename = get_base_name(path);
288 struct tfs_dir_entry *de;
289 int dirty = 0;
291 dir = tfs_namei(sbi, filename, LOOKUP_PARENT);
292 if (!dir) {
293 printf("ERROR: path not exist!\n");
294 return NULL;
297 if (de = tfs_find_entry(sbi, filename, dir)) {
298 printf("ERROR: %s exist!\n", path);
299 free_inode(dir);
300 return NULL;
303 inode = tfs_new_inode(sbi, mode);
304 if (!inode)
305 return NULL;
306 inode->i_mtime = inode->i_atime = current_time;
307 tfs_iwrite(sbi, inode);
309 if (tfs_add_entry(sbi, dir, filename, inode->i_ino, &dirty) == -1) {
310 TFS_DEBUG("trying to add a new entry: %s faild!\n", filename);
311 free_inode(dir);
312 free_inode(inode);
313 return NULL;
315 if (dirty)
316 tfs_iwrite(sbi, dir);
318 if (parent_dir)
319 *parent_dir = dir;
320 else
321 free_inode(dir);
323 return inode;
327 #if 0 /* the debug part */
328 int main(int argc, char *argv[])
331 #endif