2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright 2001-2004, ps2dev - http://www.ps2dev.org
7 # Licenced under Academic Free License version 2.0
8 # Review ps2sdk README & LICENSE files for further details.
10 # $Id: dir.c 1158 2005-06-13 22:31:13Z oopo $
11 # PFS directory parsing routines
16 // Gets a dir entry from the inode specified by clink
17 pfs_cache_t
*getDentry(pfs_cache_t
*clink
, char *path
, pfs_dentry
**dentry
, u32
*size
, int option
)
19 pfs_blockpos_t block_pos
;
24 pfs_cache_t
*dentCache
;
31 dentryLen
= (len
+8+3) &~4;
35 block_pos
.inode
= cacheUsedAdd(clink
);
36 block_pos
.block_segment
= 1;
37 block_pos
.block_offset
= 0;
38 block_pos
.byte_offset
= 0;
39 dentCache
= getDentriesChunk(&block_pos
, (int *)&result
);
43 d2
=d
=dentCache
->u
.dentry
;
44 while(*size
< clink
->u
.inode
->size
)
46 // Read another dentry chunk if we need to
47 if ((int)d2
>= ((int)dentCache
->u
.inode
+ metaSize
))
49 if (inodeSync(&block_pos
, metaSize
, clink
->u
.inode
->number_data
))
53 if ((dentCache
=getDentriesChunk(&block_pos
, (int *)&result
))==0)
55 d
=dentCache
->u
.dentry
;
58 for (d2
=(pfs_dentry
*)((int)d
+512); d
< d2
; (int)d
+=aLen
)
60 aLen
=(d
->aLen
& 0xFFF);
63 printf("ps2fs: Error: dir-entry allocated length/4 != 0\n");
66 if (aLen
< ((d
->pLen
+ 8 + 3) & 0x1FC)){
67 printf("ps2fs: Error: dir-entry is too small\n");
70 if ((u32
)d2
< ((u32
)d
+ aLen
)){
71 printf("ps2fs: Error: dir-entry across sectors\n");
75 // decide if the current dentry meets the required criteria, based on 'option'
78 case 0: // result = 1 when paths are equal
79 result
= (len
==d
->pLen
) && (memcmp(path
, d
->path
, d
->pLen
)==0);
82 result
= ((d
->inode
) || (aLen
< dentryLen
)) ? ((aLen
- ((d
->pLen
+ 8 + 3) & 0x1FC))
85 case 2: // result = 1 when dir path is not empty, "." or ".."
86 result
= d
->pLen
&& strcmp(d
->path
, ".") && strcmp(d
->path
, "..");
95 cacheAdd(block_pos
.inode
);
101 _exit
: cacheAdd(dentCache
);
103 cacheAdd(block_pos
.inode
);
107 pfs_cache_t
*getDentriesChunk(pfs_blockpos_t
*position
, int *result
)
110 pfs_mount_t
*pfsMount
=position
->inode
->pfsMount
;
112 bi
= &position
->inode
->u
.inode
->data
[fixIndex(position
->block_segment
)];
114 return cacheGetData(pfsMount
, bi
->subpart
,
115 ((bi
->number
+ position
->block_offset
) << pfsMount
->inode_scale
) +
116 position
->byte_offset
/ metaSize
, CACHE_FLAG_NOTHING
, result
);
119 int getNextDentry(pfs_cache_t
*clink
, pfs_blockpos_t
*blockpos
, u32
*position
, char *name
, pfs_blockinfo
*bi
)
126 // loop until a non-empty entry is found or until the end of the dentry chunk is reached
127 while((len
== 0) && (*position
< clink
->u
.inode
->size
))
130 if (!(dcache
=getDentriesChunk(blockpos
, &result
)))
132 dprintf("ps2fs: couldnt get dentries chunk for dread!\n");
136 dentry
= (pfs_dentry
*)((u32
)dcache
->u
.data
+ (blockpos
->byte_offset
% metaSize
));
139 memcpy(name
, dentry
->path
, len
);
142 bi
->subpart
= dentry
->sub
;
143 bi
->number
= dentry
->inode
;
146 *position
+= dentry
->aLen
& 0xFFF;
149 if (inodeSync(blockpos
, dentry
->aLen
& 0xFFF, clink
->u
.inode
->number_data
))
156 pfs_cache_t
*getDentriesAtPos(pfs_cache_t
*clink
, u64 position
, int *offset
, int *result
)
158 pfs_blockpos_t blockpos
;
160 *result
=blockInitPos(clink
, &blockpos
, position
);
161 if (*result
) return 0;
163 *offset
=blockpos
.byte_offset
% metaSize
;
165 r
=getDentriesChunk(&blockpos
, result
);
166 cacheAdd(blockpos
.inode
);
171 pfs_cache_t
*fillInDentry(pfs_cache_t
*clink
, pfs_dentry
*dentry
, char *path1
, pfs_blockinfo
*bi
, u32 len
, u16 mode
)
173 dentry
->inode
=bi
->number
;
174 dentry
->sub
=bi
->subpart
;
175 dentry
->pLen
=strlen(path1
);
176 dentry
->aLen
=len
| (mode
& FIO_S_IFMT
);
177 memcpy(dentry
->path
, path1
, dentry
->pLen
& 0xFF);
182 pfs_cache_t
*dirAddEntry(pfs_cache_t
*dir
, char *filename
, pfs_blockinfo
*bi
, u16 mode
, int *result
)
189 dcache
=getDentry(dir
, filename
, &dentry
, &size
, 1);
191 len
=dentry
->aLen
& 0xFFF;
193 len
-=(dentry
->pLen
+ 11) & 0x1FC;
194 dentry
->aLen
=(dentry
->aLen
& FIO_S_IFMT
) | ((dentry
->aLen
& 0xFFF) - len
);
195 (u32
)dentry
+=dentry
->aLen
& 0xFFF;
199 if ((*result
=ioctl2Alloc(dir
, sizeof(pfs_dentry
), 0))<0)
201 dcache
=getDentriesAtPos(dir
, dir
->u
.inode
->size
, &offset
, result
);
205 dir
->u
.inode
->size
+= sizeof(pfs_dentry
);
207 dentry
=(pfs_dentry
*)((u32
)dcache
->u
.dentry
+offset
);
208 len
=sizeof(pfs_dentry
);
210 return fillInDentry(dcache
, dentry
, filename
, bi
, len
, mode
);
213 pfs_cache_t
*dirRemoveEntry(pfs_cache_t
*clink
, char *path
)
218 pfs_dentry
*dlast
=NULL
, *dnext
;
221 if ((c
=getDentry(clink
, path
, &dentry
, &size
, 0))){
222 val
=(int)dentry
-(int)c
->u
.dentry
;
223 if (val
<0) val
+=511;
224 val
/=512; val
*=512;
225 dnext
=(pfs_dentry
*)((int)c
->u
.dentry
+val
);
229 dlast
->aLen
=(dlast
->aLen
& FIO_S_IFMT
) | ((dlast
->aLen
& 0xFFF) + (dnext
->aLen
& 0xFFF));
231 dnext
->pLen
=dnext
->inode
=0;
233 if ((clink
->u
.inode
->size
) &&
234 (0>=dnext
) && ((dnext
==0) ||//strange?!?;
235 (size
+(dnext
->aLen
& 0xFFF)>=clink
->u
.inode
->size
))) {
236 clink
->u
.inode
->size
-= dnext
->aLen
& 0xFFF;
241 i
+=dnext
->aLen
& 0xFFF;
243 (u32
)dnext
+=dnext
->aLen
& 0xFFF;
249 int checkDirForFiles(pfs_cache_t
*clink
)
255 if((dcache
=getDentry(clink
, NULL
, &dentry
, &size
, 2))){
262 void fillSelfAndParentDentries(pfs_cache_t
*clink
, pfs_blockinfo
*self
, pfs_blockinfo
*parent
)
264 pfs_dentry
*dentry
=clink
->u
.dentry
;
266 memset(dentry
, 0, metaSize
);
267 dentry
->inode
=self
->number
;
268 *(u32
*)dentry
->path
='.';
269 dentry
->sub
=self
->subpart
;
271 dentry
->aLen
=12 | FIO_S_IFDIR
;
275 dentry
->inode
=parent
->number
;
276 *(u32
*)dentry
->path
=('.'<<8) + '.';
277 dentry
->sub
=parent
->subpart
;
279 dentry
->aLen
=500 | FIO_S_IFDIR
;
282 pfs_cache_t
* setParent(pfs_cache_t
*clink
, pfs_blockinfo
*bi
, int *result
)
287 dcache
=getDentriesAtPos(clink
, 0, &offset
, result
);
289 pfs_dentry
*d
=(pfs_dentry
*)(12+(u32
)dcache
->u
.data
);