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: inode.c 911 2005-03-14 21:02:17Z oopo $
11 # PFS inode manipulation routines
16 ///////////////////////////////////////////////////////////////////////////////
18 int blockSize
=1;// block size(in sectors(512) )
21 ///////////////////////////////////////////////////////////////////////////////
22 // Function defenitions
25 void inodePrint(pfs_inode
*inode
)
27 dprintf("ps2fs: inodePrint: Checksum = 0x%lX, Magic = 0x%lX\n", inode
->checksum
, inode
->magic
);
28 dprintf("ps2fs: Mode = 0x%X, attr = 0x%X\n", inode
->mode
, inode
->attr
);
29 dprintf("ps2fs: size = 0x%08lX%08lX\n", (u32
)(inode
->size
>> 32), (u32
)(inode
->size
));
32 int inodeCheckSum(pfs_inode
*inode
)
34 u32
*ptr
=(u32
*)inode
;
38 for(i
=1; i
< 256; i
++)
43 pfs_cache_t
*inodeGetData(pfs_mount_t
*pfsMount
, u16 sub
, u32 inode
, int *result
)
45 return cacheGetData(pfsMount
, sub
, inode
<< pfsMount
->inode_scale
,
46 CACHE_FLAG_SEGD
, result
);
49 void inodeUpdateTime(pfs_cache_t
*clink
)
50 { // set the inode time's in cache
51 getPs2Time(&clink
->u
.inode
->mtime
);
52 memcpy(&clink
->u
.inode
->ctime
, &clink
->u
.inode
->mtime
, sizeof(pfs_datetime
));
53 memcpy(&clink
->u
.inode
->atime
, &clink
->u
.inode
->mtime
, sizeof(pfs_datetime
));
54 clink
->flags
|=CACHE_FLAG_DIRTY
;
57 // Returns the cached inode for the file (dir) in the directory pointed
58 // to by the dir inode.
59 pfs_cache_t
*inodeGetFileInDir(pfs_cache_t
*dirInode
, char *path
, int *result
)
66 return cacheUsedAdd(dirInode
);
68 // If we're in the root dir, dont do anything for ".."
69 if ((dirInode
->sector
==
70 dirInode
->pfsMount
->root_dir
.number
<< dirInode
->pfsMount
->inode_scale
) &&
71 (dirInode
->sub
== dirInode
->pfsMount
->root_dir
.subpart
) &&
72 (strcmp(path
, "..") == 0))
73 return cacheUsedAdd(dirInode
);
75 if ((*result
=checkAccess(dirInode
, 1)) < 0)
78 // Get dentry of file/dir specified by path from the dir pointed to
79 // by the inode (dirInode). Then return the cached inode for that dentry.
80 if ((clink
=getDentry(dirInode
, path
, &dentry
, &size
, 0))){
82 return inodeGetData(dirInode
->pfsMount
,
83 dentry
->sub
, dentry
->inode
, result
);
90 int inodeSync(pfs_blockpos_t
*blockpos
, u64 size
, u32 used_segments
)
96 for(i
=blockSyncPos(blockpos
, size
); i
; )
98 count
=blockpos
->inode
->u
.inode
->data
[fixIndex(blockpos
->block_segment
)].count
;
100 i
+=blockpos
->block_offset
;
103 blockpos
->block_offset
=i
;
109 if (blockpos
->block_segment
+ 1 == used_segments
)
111 blockpos
->block_offset
=count
;
112 if (i
|| blockpos
->byte_offset
){
113 printf("ps2fs: panic: fp exceeds file.\n");
117 blockpos
->block_offset
=0;
118 blockpos
->block_segment
++;
121 if (fixIndex(blockpos
->block_segment
))
124 if ((blockpos
->inode
= blockGetNextSegment(blockpos
->inode
, &result
)) == 0)
133 pfs_cache_t
*inodeGetFile(pfs_mount_t
*pfsMount
, pfs_cache_t
*clink
,
134 const char *name
, int *result
) {
138 c
=inodeGetParent(pfsMount
, clink
, name
, path
, result
);
140 c
=inodeGetFileInDir(c
, path
, result
);
147 void inodeFill(pfs_cache_t
*ci
, pfs_blockinfo
*bi
, u16 mode
, u16 uid
, u16 gid
)
151 memset(ci
->u
.inode
, 0, metaSize
);
153 ci
->u
.inode
->magic
=PFS_SEGD_MAGIC
;
155 ci
->u
.inode
->inode_block
.number
=bi
->number
;
156 ci
->u
.inode
->inode_block
.subpart
=bi
->subpart
;
157 ci
->u
.inode
->inode_block
.count
=bi
->count
;
159 ci
->u
.inode
->last_segment
.number
=bi
->number
;
160 ci
->u
.inode
->last_segment
.subpart
=bi
->subpart
;
161 ci
->u
.inode
->last_segment
.count
=bi
->count
;
163 ci
->u
.inode
->mode
=mode
;
164 ci
->u
.inode
->uid
=uid
;
165 ci
->u
.inode
->gid
=gid
;
167 if ((mode
& FIO_S_IFMT
) == FIO_S_IFDIR
){
168 ci
->u
.inode
->attr
=0xA0;
169 ci
->u
.inode
->size
=sizeof(pfs_dentry
);
175 ci
->u
.inode
->number_data
=ci
->u
.inode
->number_blocks
=val
;
178 getPs2Time(&ci
->u
.inode
->ctime
);
179 memcpy(&ci
->u
.inode
->atime
, &ci
->u
.inode
->ctime
, sizeof(pfs_datetime
));
180 memcpy(&ci
->u
.inode
->mtime
, &ci
->u
.inode
->ctime
, sizeof(pfs_datetime
));
182 ci
->u
.inode
->number_segdesg
=1;
183 ci
->u
.inode
->data
[0].number
=bi
->number
;
184 ci
->u
.inode
->data
[0].subpart
=bi
->subpart
;
185 ci
->u
.inode
->data
[0].count
=bi
->count
;
187 ci
->u
.inode
->subpart
=bi
->subpart
;
189 ci
->flags
|= CACHE_FLAG_DIRTY
;
193 // Given a path, this function will return the inode for the directory which holds
194 // the file (dir) specified by the filename.
196 // ie: if filename = /usr/local/ps2/games then it will return the inode for /usr/local/ps2
197 pfs_cache_t
* inodeGetParent(pfs_mount_t
*pfsMount
, pfs_cache_t
*clink
, const char *filename
,
198 char *path
, int *result
)
200 pfs_cache_t
*link
, *inode
;
201 char *filename2
=(char*)filename
;
206 if (clink
) cacheAdd(clink
);
210 if (filename2
[0] == '/')
213 // Get inode for root dir
215 if (clink
) cacheAdd(clink
);
216 if ((clink
=inodeGetData(pfsMount
, pfsMount
->root_dir
.subpart
,
217 pfsMount
->root_dir
.number
, result
))==0)
220 // dprintf("ps2fs: Got root dir inode!\n");
221 // inodePrint(clink->u.inode);
224 else if (clink
==NULL
)
227 // Otherwise if relative path, get inode for current dir
229 if ((clink
=inodeGetData(pfsMount
, pfsMount
->current_dir
.subpart
,
230 pfsMount
->current_dir
.number
, result
))==0)
233 // dprintf("ps2fs: Got current dir inode!\n");
234 // inodePrint(clink->u.inode);
239 filename2
=splitPath(filename2
, path
, result
);
240 if (filename2
==NULL
) return NULL
;
242 // If we've reached the end of the path, then we want to return
243 // the cached inode for the directory which holds the file/dir in path
246 if ((clink
->u
.inode
->mode
& FIO_S_IFMT
) == FIO_S_IFDIR
)
250 *result
=-ENOTDIR
; // not a directory
254 inode
=inodeGetFileInDir(clink
, path
, result
);
256 if (inode
&& ((inode
->u
.inode
->mode
& FIO_S_IFMT
) == FIO_S_IFLNK
))
258 if (symbolicLinks
>= 4)
260 *result
=-ELOOP
; // too many symbolic links
267 link
=inodeGetFile(pfsMount
, clink
, (char*)&inode
->u
.inode
->data
[1], result
);
286 int inodeRemove(pfs_cache_t
*parent
, pfs_cache_t
*inode
, char *path
)
291 if((entry
=dirRemoveEntry(parent
, path
))!=NULL
)
293 inodeUpdateTime(parent
);
294 entry
->flags
|=CACHE_FLAG_DIRTY
;
303 inode
->flags
&=~CACHE_FLAG_DIRTY
;
304 bitmapFreeInodeBlocks(inode
);
305 if(parent
->pfsMount
->flags
& FIO_ATTR_WRITEABLE
)
306 cacheFlushAllDirty(parent
->pfsMount
);
313 pfs_cache_t
*inodeCreateNewFile(pfs_cache_t
*clink
, u16 mode
, u16 uid
, u16 gid
, int *result
)
317 pfs_mount_t
*pfsMount
=clink
->pfsMount
;
322 if ((mode
& FIO_S_IFMT
) == FIO_S_IFDIR
)
324 if (pfsMount
->num_subs
> clink
->u
.inode
->subpart
)
325 clink
->u
.inode
->subpart
++;
327 clink
->u
.inode
->subpart
=0;
329 a
.subpart
=clink
->u
.inode
->subpart
;
330 j
= (pfsMount
->zfree
* (u64
)100) / pfsMount
->total_sector
;
331 i
= (pfsMount
->free_zone
[a
.subpart
] * (u64
)100) /
332 (pfsMount
->blockDev
->getSize(pfsMount
->fd
, a
.subpart
) >> pfsMount
->sector_scale
);
333 if ((i
< j
) && ((j
-i
) >= 11))
334 a
.subpart
=getMaxthIndex(pfsMount
);
336 a
.number
=clink
->u
.inode
->inode_block
.number
;
337 a
.subpart
=clink
->u
.inode
->inode_block
.subpart
;
338 a
.count
=clink
->u
.inode
->inode_block
.count
;
342 // Search for a free zone, starting from parent dir inode block
343 *result
=searchFreeZone(pfsMount
, &a
, 2);
344 if (*result
<0) return 0;
345 inode
=cacheGetData(pfsMount
, a
.subpart
, a
.number
<< pfsMount
->inode_scale
,
346 CACHE_FLAG_SEGD
| CACHE_FLAG_NOLOAD
, result
);
350 // Initialise the inode (which has been allocate blocks specified by a)
351 inodeFill(inode
, (pfs_blockinfo
*)&a
, mode
, uid
, gid
);
352 if ((mode
& FIO_S_IFMT
) != FIO_S_IFDIR
)
359 *result
=searchFreeZone(pfsMount
, (pfs_blockinfo
*)&a
, 0);
362 bitmapFreeBlockSegment(pfsMount
, (pfs_blockinfo
*)&b
);
366 inode
->u
.inode
->data
[1].number
=a
.number
;
367 inode
->u
.inode
->data
[1].subpart
=a
.subpart
;
368 inode
->u
.inode
->data
[1].count
=a
.count
;