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 tfs_dir_entry
* tfs_find_entry(struct tfs_sb_info
*sbi
,
29 struct tfs_dir_entry
*de
;
30 struct cache_struct
*cs
;
32 block
= inode
->i_data
[index
++];
34 cs
= get_cache_block(sbi
, block
);
35 de
= (struct tfs_dir_entry
*)cs
->data
;
37 while(i
< (int)inode
->i_size
) {
38 if ((char *)de
>= (char *)cs
->data
+ sbi
->s_block_size
) {
39 if ((block
= inode
->i_data
[index
++]) < sbi
->s_data_area
)
41 cs
= get_cache_block(sbi
, block
);
42 de
= (struct tfs_dir_entry
*)cs
->data
;
44 if (tfs_match_entry(dname
, de
))
53 int tfs_add_entry(struct tfs_sb_info
*sbi
, struct inode
*dir
, const char *name
, int inr
, int * dirty
)
57 struct cache_struct
*cs
;
58 struct tfs_dir_entry
*de
;
60 if (strlen(name
) > TFS_NAME_LEN
) {
61 printf("ERROR: file name too long!\n");
65 if (!(block
= dir
->i_data
[index
++]))
67 cs
= get_cache_block(sbi
, block
);
68 de
= (struct tfs_dir_entry
*)cs
->data
;
69 while (i
<= (int)dir
->i_size
) {
70 if ((void *)de
>= cs
->data
+ sbi
->s_block_size
) {
71 if (!(block
= dir
->i_data
[index
++]))
73 cs
= get_cache_block(sbi
, block
);
74 de
= (struct tfs_dir_entry
*)cs
->data
;
78 i
+= sizeof(struct tfs_dir_entry
);
85 /* allocate a new block to hold the new entry */
87 block
= tfs_alloc_block(sbi
, sbi
->s_data_area
);
88 dir
->i_data
[index
- 1] = block
;
90 printf("ERROR: allocate new block failed, out of space!\n");
93 cs
= get_cache_block(sbi
, block
);
94 de
= (struct tfs_dir_entry
*)cs
->data
;
95 memset(cs
->data
, 0, sbi
->s_block_size
);
97 * tell the cache system to update the cache block
98 * in the next time read
103 * This will go through the next if sentence, since if we
104 * allocated a new entry, then 'i >= dir->i_size' would
109 if (i
>= dir
->i_size
) {
110 /* Add a new entry at last */
111 dir
->i_size
+= sizeof(struct tfs_dir_entry
);
113 /* tell the caller to update this inode */
118 * Else, we find a unused hole, this usually happens when user
119 * removes a file or directory, so we can just fill up
120 * the hole, and do not need allocate more space.
123 memcpy(de
->d_name
, name
, strlen(name
));
125 /* write the entry back to disk */
126 tfs_bwrite(sbi
, block
, cs
->data
);
132 int tfs_mkdir(struct tfs_sb_info
*sbi
, const char *path
)
135 struct inode
*parent_dir
;
139 dir
= tfs_mknod(sbi
, path
, TFS_DIR
, &parent_dir
);
141 TFS_DEBUG("mknod for path failed!\n");
145 res
= tfs_add_entry(sbi
, dir
, ".", dir
->i_ino
, &dirty
);
147 TFS_DEBUG("trying to add '.' under %s failed!\n", path
);
151 res
= tfs_add_entry(sbi
, dir
, "..", parent_dir
->i_ino
, &dirty
);
153 TFS_DEBUG("trying to add .. under %s failed!\n", path
);
158 tfs_iwrite(sbi
, dir
);
161 free_inode(parent_dir
);
167 /* read one directry entry at a time */
168 static struct dirent
* tfs_readdir(struct tfs_sb_info
*sbi
, struct inode
*inode
, uint32_t offset
)
170 struct dirent
*dirent
;
171 struct tfs_dir_entry
*de
;
172 struct cache_struct
*cs
;
173 int index
= offset
>> sbi
->s_block_shift
;
176 if (!(block
= inode
->i_data
[index
]))
178 cs
= get_cache_block(sbi
, block
);
179 de
= (struct tfs_dir_entry
*)(cs
->data
+ (offset
& (sbi
->s_block_size
- 1)));
181 if (!(dirent
= malloc(sizeof(*dirent
)))) {
182 printf("malloc dirent structure in tfs_readdir error!\n");
185 memset(dirent
, 0, sizeof(*dirent
));
186 dirent
->d_ino
= de
->d_inode
;
187 dirent
->d_off
= offset
;
188 dirent
->d_reclen
= sizeof(struct tfs_dir_entry
);
190 memcpy(dirent
->d_name
, de
->d_name
, TFS_NAME_LEN
);
196 #if 0 /* the debug part */
197 int main(int argc
, char *argv
[])