11 * NOTE! unlike strncmp, ext2_match_entry returns 1 for success, 0 for failure.
13 * len <= EXT2_NAME_LEN and de != NULL are guaranteed by caller.
15 static inline int tfs_match_entry (const char * const name
,
16 struct tfs_dir_entry
* de
)
20 if (strlen(name
) != strlen(de
->d_name
) && strlen(name
) != TFS_NAME_LEN
)
22 return !strncmp(name
, de
->d_name
, strlen(name
));
27 * NULL, entry not found
28 * ERROR, errors happend.
31 struct cache_struct
* tfs_find_entry(struct inode
*inode
, const char *dname
, struct tfs_dir_entry
**res
)
35 struct tfs_dir_entry
*de
;
36 struct cache_struct
*cs
;
37 struct tfs_sb_info
*sbi
= TFS_SBI(inode
->i_fs
);
39 block
= inode
->i_data
[index
++];
42 cs
= get_cache_block(inode
->i_fs
, block
);
45 de
= (struct tfs_dir_entry
*)cs
->data
;
48 if ((char *)de
>= (char *)cs
->data
+ sbi
->s_block_size
) {
49 if ((block
= inode
->i_data
[index
++]) < sbi
->s_data_area
)
51 cs
= get_cache_block(inode
->i_fs
, block
);
54 de
= (struct tfs_dir_entry
*)cs
->data
;
56 if (de
->d_inode
== 0) {
60 if (tfs_match_entry(dname
, de
)) {
71 int tfs_add_entry(struct inode
*dir
, const char *name
, int inr
, int * dirty
)
75 struct cache_struct
*cs
;
76 struct tfs_dir_entry
*de
;
77 struct tfs_sb_info
*sbi
= TFS_SBI(dir
->i_fs
);
79 if (strlen(name
) > TFS_NAME_LEN
)
82 if (!(block
= dir
->i_data
[index
++]))
84 cs
= get_cache_block(dir
->i_fs
, block
);
87 de
= (struct tfs_dir_entry
*)cs
->data
;
89 if ((void *)de
>= cs
->data
+ sbi
->s_block_size
) {
90 if (!(block
= dir
->i_data
[index
++]))
92 cs
= get_cache_block(dir
->i_fs
, block
);
95 de
= (struct tfs_dir_entry
*)cs
->data
;
105 /* allocate a new block to hold the new entry */
107 block
= tfs_alloc_block(sbi
, sbi
->s_data_area
);
110 if (index
> TFS_N_BLOCKS
)
113 dir
->i_data
[index
- 1] = block
;
114 cs
= get_cache_block(dir
->i_fs
, block
);
117 de
= (struct tfs_dir_entry
*)cs
->data
;
118 memset(cs
->data
, 0, sbi
->s_block_size
);
121 /* Add a new entry at last */
122 dir
->i_size
+= sizeof(struct tfs_dir_entry
);
123 /* tell the caller to update this inode */
126 memset(de
, 0, sizeof(*de
));
128 memcpy(de
->d_name
, name
, strlen(name
));
130 /* write the entry back to disk */
131 if (tfs_bwrite(sbi
, block
, cs
->data
))
138 int tfs_mkdir(struct inode
*parent_dir
, const char *dname
)
144 dir
= tfs_mknod(parent_dir
, dname
, TFS_DIR
);
146 free_inode(parent_dir
);
150 err
= tfs_add_entry(dir
, ".", dir
->i_ino
, &dirty
);
154 err
= tfs_add_entry(dir
, "..", parent_dir
->i_ino
, &dirty
);
159 err
= tfs_iwrite(dir
);
162 free_inode(parent_dir
);
168 * Check if the dir is empty or not.
170 static int is_empty_dir(struct inode
*dir
)
172 if (dir
->i_size
> 2 * sizeof(struct tfs_dir_entry
))
174 else if (dir
->i_size
< 2 * sizeof(struct tfs_dir_entry
))
181 int tfs_rmdir(struct inode
*dir
, const char *dname
)
184 struct cache_struct
*cs
;
185 struct tfs_dir_entry
*de
;
186 struct tfs_sb_info
*sbi
= TFS_SBI(dir
->i_fs
);
190 cs
= tfs_find_entry(dir
, dname
, &de
);
191 if (IS_ERR_OR_NULL(cs
)) {
192 err
= cs
? PTR_ERR(cs
) : -ENOENT
;
196 inode
= tfs_iget_by_inr(dir
->i_fs
, de
->d_inode
);
198 err
= PTR_ERR(inode
);
202 if (inode
->i_mode
!= TFS_DIR
) {
207 err
= is_empty_dir(inode
);
211 } else if (err
== -1) {
212 printk("%s: path correupted: the size is less than two direntry!\n", dname
);
217 dir
->i_size
-= sizeof(struct tfs_dir_entry
);
218 err
= tfs_iwrite(dir
);
222 err
= tfs_bwrite(sbi
, cs
->block
, cs
->data
);
225 err
= tfs_release_inode(sbi
, inode
);
235 int tfs_unlink(struct inode
*dir
, const char *dname
)
238 struct cache_struct
*cs
;
239 struct tfs_dir_entry
*de
;
240 struct tfs_sb_info
*sbi
= TFS_SBI(dir
->i_fs
);
243 cs
= tfs_find_entry(dir
, dname
, &de
);
244 if (IS_ERR_OR_NULL(cs
)) {
245 err
= cs
? PTR_ERR(cs
) : -ENOENT
;
249 inode
= tfs_iget_by_inr(dir
->i_fs
, de
->d_inode
);
251 err
= PTR_ERR(inode
);
255 if (inode
->i_mode
!= TFS_FILE
) {
256 printk("%s: not a file!\n", dname
);
260 dir
->i_size
-= sizeof(struct tfs_dir_entry
);
261 err
= tfs_iwrite(dir
);
265 err
= tfs_bwrite(sbi
, cs
->block
, cs
->data
);
268 err
= tfs_release_inode(sbi
, inode
);
278 /* read one directry entry at a time */
279 struct dirent
* tfs_readdir(struct file
*file
)
281 struct dirent
*dirent
;
282 struct tfs_dir_entry
*de
;
283 struct cache_struct
*cs
;
284 struct inode
*inode
= file
->inode
;
285 struct tfs_sb_info
*sbi
= TFS_SBI(file
->fs
);
286 int index
= file
->offset
>> sbi
->s_block_shift
;
289 if (!(block
= tfs_bmap(inode
, index
)))
291 cs
= get_cache_block(file
->fs
, block
);
292 de
= (struct tfs_dir_entry
*)(cs
->data
+ (file
->offset
& (sbi
->s_block_size
- 1)));
294 if (!(dirent
= malloc(sizeof(*dirent
)))) {
295 printk("malloc dirent structure in tfs_readdir error!\n");
298 memset(dirent
, 0, sizeof(*dirent
));
299 dirent
->d_ino
= de
->d_inode
;
300 dirent
->d_off
= file
->offset
;
301 dirent
->d_reclen
= sizeof(struct tfs_dir_entry
);
303 memcpy(dirent
->d_name
, de
->d_name
, TFS_NAME_LEN
);
305 file
->offset
+= sizeof(struct tfs_dir_entry
);
307 /* Skip the invalid one */
308 if (de
->d_inode
== 0) {
310 return tfs_readdir(file
);
317 void tfs_closedir(DIR *dir
)
320 free_inode(dir
->dd_dir
->inode
);