10 * NOTE! unlike strncmp, ext2_match_entry returns 1 for success, 0 for failure.
12 * len <= EXT2_NAME_LEN and de != NULL are guaranteed by caller.
14 static inline int tfs_match_entry (const char * const name
,
15 struct tfs_dir_entry
* de
)
19 return !strncmp(name
, de
->d_name
, strlen(name
));
22 struct cache_struct
* tfs_find_entry(struct tfs_sb_info
*sbi
,
25 struct tfs_dir_entry
**res
)
29 struct tfs_dir_entry
*de
;
30 struct cache_struct
*cs
;
32 block
= inode
->i_data
[index
++];
35 cs
= get_cache_block(sbi
, block
);
36 de
= (struct tfs_dir_entry
*)cs
->data
;
39 if ((char *)de
>= (char *)cs
->data
+ sbi
->s_block_size
) {
40 if ((block
= inode
->i_data
[index
++]) < sbi
->s_data_area
)
42 cs
= get_cache_block(sbi
, block
);
43 de
= (struct tfs_dir_entry
*)cs
->data
;
45 if (de
->d_inode
== 0) {
49 if (tfs_match_entry(dname
, de
)) {
60 int tfs_add_entry(struct tfs_sb_info
*sbi
, struct inode
*dir
, const char *name
, int inr
, int * dirty
)
64 struct cache_struct
*cs
;
65 struct tfs_dir_entry
*de
;
67 if (strlen(name
) > TFS_NAME_LEN
) {
68 printk("ERROR: file name too long!\n");
72 if (!(block
= dir
->i_data
[index
++]))
74 cs
= get_cache_block(sbi
, block
);
75 de
= (struct tfs_dir_entry
*)cs
->data
;
77 if ((void *)de
>= cs
->data
+ sbi
->s_block_size
) {
78 if (!(block
= dir
->i_data
[index
++]))
80 cs
= get_cache_block(sbi
, block
);
81 de
= (struct tfs_dir_entry
*)cs
->data
;
91 /* allocate a new block to hold the new entry */
93 block
= tfs_alloc_block(sbi
, sbi
->s_data_area
);
95 printk("ERROR: allocate new block failed, out of space!\n");
98 if (index
> TFS_N_BLOCKS
) {
99 printk("file too big!\n");
102 dir
->i_data
[index
- 1] = block
;
103 cs
= get_cache_block(sbi
, block
);
104 de
= (struct tfs_dir_entry
*)cs
->data
;
105 memset(cs
->data
, 0, sbi
->s_block_size
);
108 /* Add a new entry at last */
109 dir
->i_size
+= sizeof(struct tfs_dir_entry
);
110 /* tell the caller to update this inode */
113 memset(de
, 0, sizeof(*de
));
115 memcpy(de
->d_name
, name
, strlen(name
));
117 /* write the entry back to disk */
118 tfs_bwrite(sbi
, block
, cs
->data
);
124 int tfs_mkdir(struct tfs_sb_info
*sbi
, const char *path
)
127 struct inode
*parent_dir
;
131 dir
= tfs_mknod(sbi
, path
, TFS_DIR
, &parent_dir
);
133 TFS_DEBUG("mknod for path failed!\n");
137 res
= tfs_add_entry(sbi
, dir
, ".", dir
->i_ino
, &dirty
);
139 TFS_DEBUG("trying to add '.' under %s failed!\n", path
);
143 res
= tfs_add_entry(sbi
, dir
, "..", parent_dir
->i_ino
, &dirty
);
145 TFS_DEBUG("trying to add .. under %s failed!\n", path
);
150 tfs_iwrite(sbi
, dir
);
153 if (this_dir
->dd_dir
->inode
!= parent_dir
)
154 free_inode(parent_dir
);
161 * Check if the dir is empty or not.
163 static int is_empty_dir(struct tfs_sb_info
*sbi
, struct inode
*dir
)
165 if (dir
->i_size
> 2 * sizeof(struct tfs_dir_entry
))
167 else if (dir
->i_size
< 2 * sizeof(struct tfs_dir_entry
))
174 int tfs_rmdir(struct tfs_sb_info
*sbi
, const char *path
)
179 struct cache_struct
*cs
;
180 struct tfs_dir_entry
*de
;
181 const char * base_name
= get_base_name(path
);
184 printk("%s: invalid path name!\n", path
);
188 dir
= tfs_namei(sbi
, path
, LOOKUP_PARENT
);
190 printk("ERROR: path not exist!\n");
194 cs
= tfs_find_entry(sbi
, base_name
, dir
, &de
);
196 printk("%s: path not exist!\n", path
);
200 inode
= tfs_iget_by_inr(sbi
, de
->d_inode
);
202 printk("%s: path not exist!\n", path
);
205 if (inode
->i_mode
!= TFS_DIR
) {
206 printk("%s: not a directory!\n", path
);
210 res
= is_empty_dir(sbi
, inode
);
212 printk("%s: path not empty!\n", path
);
214 } else if (res
== -1) {
215 printk("%s: path correupted: the size is less than two direntry!\n", path
);
219 dir
->i_size
-= sizeof(struct tfs_dir_entry
);
220 tfs_iwrite(sbi
, dir
);
222 tfs_bwrite(sbi
, cs
->block
, cs
->data
);
223 tfs_release_inode(sbi
, inode
);
229 int tfs_unlink(struct tfs_sb_info
*sbi
, const char *path
)
234 struct cache_struct
*cs
;
235 struct tfs_dir_entry
*de
;
236 const char * base_name
= get_base_name(path
);
239 printk("%s: invalid path name!\n", path
);
243 dir
= tfs_namei(sbi
, path
, LOOKUP_PARENT
);
245 printk("ERROR: path not exist!\n");
249 cs
= tfs_find_entry(sbi
, base_name
, dir
, &de
);
251 printk("%s: path not exist!\n", path
);
255 inode
= tfs_iget_by_inr(sbi
, de
->d_inode
);
257 printk("%s: path not exist!\n", path
);
260 if (inode
->i_mode
!= TFS_FILE
) {
261 printk("%s: not a file!\n", path
);
265 dir
->i_size
-= sizeof(struct tfs_dir_entry
);
266 tfs_iwrite(sbi
, dir
);
268 tfs_bwrite(sbi
, cs
->block
, cs
->data
);
269 tfs_release_inode(sbi
, inode
);
275 /* for relative path searching */
278 DIR *tfs_opendir(struct tfs_sb_info
*sbi
, const char *path
)
280 DIR *dir
= malloc(sizeof(*dir
));
283 printk("malloc for DIR structure error!\n");
287 dir
->dd_dir
= tfs_open(sbi
, path
, 0);
296 /* read one directry entry at a time */
297 struct dirent
* tfs_readdir(DIR *dir
)
299 struct dirent
*dirent
;
300 struct tfs_dir_entry
*de
;
301 struct cache_struct
*cs
;
302 struct file
*file
= dir
->dd_dir
;
303 struct inode
*inode
= file
->inode
;
304 struct tfs_sb_info
*sbi
= file
->sbi
;
305 int index
= file
->offset
>> sbi
->s_block_shift
;
308 if (!(block
= tfs_bmap(inode
, index
)))
310 cs
= get_cache_block(sbi
, block
);
311 de
= (struct tfs_dir_entry
*)(cs
->data
+ (file
->offset
& (sbi
->s_block_size
- 1)));
313 if (!(dirent
= malloc(sizeof(*dirent
)))) {
314 printk("malloc dirent structure in tfs_readdir error!\n");
317 memset(dirent
, 0, sizeof(*dirent
));
318 dirent
->d_ino
= de
->d_inode
;
319 dirent
->d_off
= file
->offset
;
320 dirent
->d_reclen
= sizeof(struct tfs_dir_entry
);
322 memcpy(dirent
->d_name
, de
->d_name
, TFS_NAME_LEN
);
324 file
->offset
+= sizeof(struct tfs_dir_entry
);
326 /* Skip the invalid one */
327 if (de
->d_inode
== 0) {
329 return tfs_readdir(dir
);
336 void tfs_closedir(DIR *dir
)
339 free_inode(dir
->dd_dir
->inode
);