dir stuff and part of fs-write stuff added
[tfsprogs.git] / inode.c
blob5214c1332cb5f7d237770eac88153422760e81c5
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;
93 static void tfs_fill_inode(struct inode *inode, struct tfs_inode *tinode)
95 //inode->i_mode = get_mode(tinode->i_mode);
96 inode->i_mode = tinode->i_mode;
97 inode->i_size = tinode->i_size;
98 inode->i_atime = tinode->i_atime;
99 inode->i_ctime = tinode->i_ctime;
100 inode->i_mtime = tinode->i_mtime;
101 inode->i_dtime = tinode->i_dtime;
102 inode->i_flags = tinode->i_flags;
104 memcpy(inode->i_data, tinode->i_block, TFS_N_BLOCKS * sizeof(uint32_t *));
107 static int tfs_read_inode(struct tfs_sb_info *sbi, struct tfs_inode *tinode, int inr)
109 uint32_t inode_block;
110 struct cache_struct *cs;
112 inode_block = sbi->s_inode_table + (inr - 1) / TFS_INODES_PER_BLOCK(sbi);
113 cs = get_cache_block(sbi, inode_block);
114 if (!cs)
115 return -1;
117 memcpy(tinode, cs->data + ((inr - 1) % TFS_INODES_PER_BLOCK(sbi)) * sizeof(*tinode), sizeof(*tinode));
119 return 0;
122 struct inode * tfs_iget_by_inr(struct tfs_sb_info *sbi, int inr)
124 struct inode *inode;
125 struct tfs_inode tinode;
127 if (tfs_read_inode(sbi, &tinode, inr) == -1) {
128 printf("ERROR: read disk inode error!\n");
129 return NULL;
132 inode = new_inode(0);
133 if (inode) {
134 tfs_fill_inode(inode, &tinode);
135 inode->i_ino = inr;
138 return inode;
141 static struct inode *tfs_iget_root(struct tfs_sb_info *sbi)
143 return tfs_iget_by_inr(sbi, TFS_ROOT_INODE);
146 static struct inode *tfs_iget(struct tfs_sb_info * sbi, char *dname, struct inode *dir)
148 struct tfs_dir_entry *de;
150 //de = tfs_find_entry(dname, dir);
151 if (!de)
152 return NULL;
154 return tfs_iget_by_inr(sbi, de->d_inode);
157 static void *tfs_write_inode(struct tfs_inode *tinode, struct inode *inode)
159 tinode->i_mode = inode->i_mode;
160 tinode->i_size = inode->i_size;
161 tinode->i_atime = inode->i_atime;
162 tinode->i_ctime = inode->i_ctime;
163 tinode->i_mtime = inode->i_mtime;
164 tinode->i_dtime = inode->i_dtime;
165 tinode->i_flags = inode->i_flags;
167 memcpy(tinode->i_block, inode->i_data, TFS_N_BLOCKS * sizeof(uint32_t *));
168 tinode->i_reserved[0] = 0;
171 static void *tfs_iwrite(struct tfs_sb_info *sbi, struct inode *inode)
173 struct cache_struct *cs;
174 struct tfs_inode *tinode;
175 uint32_t inode_block;
177 inode_block = sbi->s_inode_table + (inode->i_ino - 1) / TFS_INODES_PER_BLOCK(sbi);
178 cs = get_cache_block(sbi, inode_block);
179 tinode = (struct tfs_inode *)cs->data + ((inode->i_ino - 1) % TFS_INODES_PER_BLOCK(sbi));
180 tfs_write_inode(tinode, inode);
181 tfs_bwrite(sbi, inode_block, cs->data);
182 cs->outdate = 1;
186 struct inode * namei(struct tfs_sb_info *sbi, const char *name, uint32_t flag)
188 struct inode *inode;
189 struct inode *parent;
190 char part[TFS_NAME_LEN + 1];
191 char *p;
193 if (*name == '/') {
194 inode = tfs_iget_root(sbi);
195 while (*name == '/')
196 name++;
197 } else {
198 printf("ERROR: relative path searching is not supported for now!\n");
199 return NULL;
201 parent = inode;
203 while (*name) {
204 p = part;
205 while (*name && *name != '/') {
206 if (p >= part + TFS_NAME_LEN) {
207 printf("ERROR: file name to long!\n");
208 return NULL;
210 *p++ = *name++;
212 *p = '\0';
213 while (*name && *name == '/')
214 name++;
215 if (!*name && (flag & LOOKUP_PARENT))
216 return parent;
217 inode = tfs_iget(sbi, part, parent);
218 if (!inode)
219 return NULL;
221 free_inode(parent);
222 parent = inode;
223 if (!*name)
224 break;
227 return inode;
230 static char *__strrchr(const char *s, int c)
232 const char *end = s + strlen(s) - 1;
233 while (*end != c && end >= s)
234 end--;
235 if (end < s)
236 return NULL;
237 return end;
240 static char *get_base_name(const char *path_org)
242 char *p;
243 char *path = strdup(path_org);
245 p = strrchr(path, '/');
246 if (!p)
247 return NULL;
248 /* the /linux/hello/ case */
249 if (*(p + 1) == 0) {
250 *p = 0;
251 p--;
252 while (*p != '/' && p >= path) {
253 *p = 0;
254 p--;
256 if (p < path)
257 return NULL;
260 return p;
263 struct inode * tfs_mknod(struct tfs_sb_info *sbi, const char *path, int mode)
265 struct inode *dir;
266 struct inode *inode;
267 const char *filename = get_base_name(path);
268 struct tfs_dir_entry *de;
269 int dirty = 0;
271 dir = namei(sbi, filename, LOOKUP_PARENT);
272 if (!dir) {
273 printf("ERROR: path not exist!\n");
274 return NULL;
277 if (de = tfs_find_entry(sbi, filename, dir)) {
278 printf("ERROR: %s exist!\n", path);
279 return NULL;
282 inode = tfs_new_inode(sbi, mode);
283 if (!inode)
284 return NULL;
285 inode->i_mtime = inode->i_atime = current_time;
286 tfs_iwrite(sbi, inode);
288 if (tfs_add_entry(sbi, dir, filename, inode->i_ino, &dirty) == -1) {
289 TFS_DEBUG("trying to add a new entry: %s faild!\n", filename);
290 return NULL;
292 if (dirty)
293 tfs_iwrite(sbi, dir);
295 return inode;
299 #if 0 /* the debug part */
300 int main(int argc, char *argv[])
303 #endif