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: pfs_fio.c 1491 2009-01-04 23:46:22Z oopo $
11 # PFS I/O manager related routines
16 ///////////////////////////////////////////////////////////////////////////////
19 u8 openFlagArray
[] = { 0, 4, 2, 6, 0, 0, 0, 0 };
20 int symbolicLinks
= 0;
22 pfs_file_slot_t
*fileSlots
;
24 ///////////////////////////////////////////////////////////////////////////////
25 // Function defenitions
27 int checkForLastError(pfs_mount_t
*pfsMount
, int rv
)
29 return pfsMount
->lastError
? pfsMount
->lastError
: rv
;
32 int checkFileSlot(pfs_file_slot_t
*fileSlot
)
36 if(fileSlot
->clink
==NULL
)
38 SignalSema(pfsFioSema
);
45 void closeFileSlot(pfs_file_slot_t
*fileSlot
)
47 pfs_mount_t
*pfsMount
=fileSlot
->clink
->pfsMount
;
49 if(fileSlot
->fd
->mode
& O_WRONLY
)
51 if(fileSlot
->restsInfo
.dirty
!=0)
53 pfsMount
->blockDev
->transfer(pfsMount
->fd
, fileSlot
->restsBuffer
,
54 fileSlot
->restsInfo
.sub
, fileSlot
->restsInfo
.sector
, 1, IOCTL2_TMODE_WRITE
);
56 inodeUpdateTime(fileSlot
->clink
); // set time :P
57 fileSlot
->clink
->u
.inode
->attr
|=FIO_ATTR_CLOSED
;
58 if(pfsMount
->flags
& FIO_ATTR_WRITEABLE
)
59 cacheFlushAllDirty(pfsMount
);
61 cacheAdd(fileSlot
->block_pos
.inode
);
62 cacheAdd(fileSlot
->clink
);
63 memset(fileSlot
, 0, sizeof(pfs_file_slot_t
));
66 pfs_mount_t
*fioGetMountedUnit(int unit
)
68 pfs_mount_t
*pfsMount
;
71 if((pfsMount
=getMountedUnit(unit
))==NULL
)
72 SignalSema(pfsFioSema
);
76 int mountDevice(block_device
*blockDev
, int fd
, int unit
, int flag
)
81 if((u32
)unit
>= pfsConfig
.maxMount
)
84 if(pfsMountBuf
[unit
].flags
& MOUNT_BUSY
)
87 for(i
= 0; i
< pfsConfig
.maxMount
; i
++)
88 if((pfsMountBuf
[i
].flags
& MOUNT_BUSY
) &&
89 (blockDev
== pfsMountBuf
[i
].blockDev
) &&
90 (fd
== pfsMountBuf
[i
].fd
)) // Cant mount the same partition more than once
93 // dprintf("ps2fs: Found free mount buffer!\n");
95 pfsMountBuf
[unit
].blockDev
= blockDev
;
96 pfsMountBuf
[unit
].fd
= fd
;
97 pfsMountBuf
[unit
].flags
= flag
;
99 rv
= mountSuperBlock(&pfsMountBuf
[unit
]);
103 pfsMountBuf
[unit
].flags
|= MOUNT_BUSY
;
104 dprintf("ps2fs: mount successfull!\n");
109 int openFile(pfs_mount_t
*pfsMount
, pfs_file_slot_t
*freeSlot
, const char *filename
, int openFlags
, int mode
)
112 int result
, result2
, result3
, result4
;
113 pfs_cache_t
*parentInode
, *fileInode
, *cached
;
116 result
= 0; //no error
117 // Get the inode for the directory which contains the file (dir) in filename
118 // After this call, 'file' will contain the name of the file we're operating on.
119 if ((parentInode
=inodeGetParent(pfsMount
, NULL
, filename
, file
, &result
))==0)
121 dprintf("ps2fs: Failed to get parent inode\n");
125 // dprintf("ps2fs: Got parent inode!\n");
126 // inodePrint(parentInode->u.inode);
128 // Get the inode for the actual file/directory contained in the parent dir
129 fileInode
=inodeGetFileInDir(parentInode
, file
, &result
);
131 // dprintf("ps2fs: got file inode! (file: %s)\n", file);
132 // inodePrint(fileInode->u.inode);
134 // If file already exists..
140 dprintf("ps2fs: File inode already exists\n");
143 flags
=openFlagArray
[openFlags
& O_RDWR
];
144 if (openFlags
& O_TRUNC
) flags
|= 2;
145 if (openFlags
& FDIRO
) flags
|= 4;
146 if ((mode
& 0x10000) ||
147 ((openFlags
& (O_CREAT
|O_EXCL
)) == (O_CREAT
|O_EXCL
))){
154 // Resolve actual file from a symlink
155 while ((fileInode
->u
.inode
->mode
& FIO_S_IFMT
) == FIO_S_IFLNK
)
157 dprintf("ps2fs: Resolving symlink..\n");
165 parentInode
=inodeGetParent(pfsMount
, parentInode
, (char*)&fileInode
->u
.inode
->data
[1],
168 if ((parentInode
==0) ||
169 ((fileInode
=inodeGetFileInDir(parentInode
, file
, &result
))==0))
173 // Make sure that if a file is being opened, then inode does not point
174 // to a directory, and vice versa.
175 if ((openFlags
& FDIRO
) == 0)
177 if ((fileInode
->u
.inode
->mode
& FIO_S_IFMT
) == FIO_S_IFDIR
)
180 if ((fileInode
->u
.inode
->mode
& FIO_S_IFMT
) != FIO_S_IFDIR
)
184 // Truncate file if required
186 ((result
=checkAccess(fileInode
, flags
& 0xFFFF))==0) &&
187 (openFlags
& O_TRUNC
))
190 dprintf("ps2fs: Truncating file..\n");
192 cached
=cacheGetData(fileInode
->pfsMount
, fileInode
->sub
, fileInode
->sector
+1, CACHE_FLAG_NOLOAD
| CACHE_FLAG_NOTHING
, &result2
);
195 memset(cached
->u
.aentry
, 0, sizeof(pfs_inode
)); //1024
196 cached
->u
.aentry
->aLen
=sizeof(pfs_inode
);
197 cached
->flags
|= CACHE_FLAG_DIRTY
;
200 if ((result
!=result2
))
202 fileInode
->u
.inode
->size
= 0;
203 fileInode
->u
.inode
->attr
&= ~FIO_ATTR_CLOSED
; //~0x80==0xFF7F
204 fileInode
->flags
|= CACHE_FLAG_DIRTY
;
205 ioctl2Free(fileInode
);
210 // Otherwise, if file doesnt already exist..
213 dprintf("ps2fs: File inode does not exist..\n");
215 if ((openFlags
& O_CREAT
) && (result
==-ENOENT
) &&
216 ((result
=checkAccess(parentInode
, 2))==0) &&
217 (fileInode
=inodeCreateNewFile(parentInode
, mode
, pfsMount
->uid
,
218 pfsMount
->gid
, &result
)))
220 if ((mode
& FIO_S_IFMT
) == FIO_S_IFLNK
)
222 strcpy((char*)&fileInode
->u
.inode
->data
[1], (char*)freeSlot
);
226 // If new file is a directory, the fill self and parent entries
227 if ((mode
& FIO_S_IFMT
) == FIO_S_IFDIR
)
229 cached
=cacheGetData(fileInode
->pfsMount
, fileInode
->u
.inode
->data
[1].subpart
,
230 fileInode
->u
.inode
->data
[1].number
<< fileInode
->pfsMount
->inode_scale
,
231 CACHE_FLAG_NOLOAD
| CACHE_FLAG_NOTHING
, &result3
);
234 fillSelfAndParentDentries(cached
,
235 &fileInode
->u
.inode
->inode_block
,
236 &parentInode
->u
.inode
->inode_block
);
237 cached
->flags
|= CACHE_FLAG_DIRTY
;
241 // Otherwise if its just a regular file, just zero its attribute entry
243 cached
=cacheGetData(fileInode
->pfsMount
, fileInode
->sub
, fileInode
->sector
+1,
244 CACHE_FLAG_NOLOAD
| CACHE_FLAG_NOTHING
, &result4
);
247 memset(cached
->u
.aentry
, 0, sizeof(pfs_inode
));
248 cached
->u
.aentry
->aLen
=sizeof(pfs_inode
);
249 cached
->flags
|= CACHE_FLAG_DIRTY
;
255 // Link new file with parent directory
256 if ((result
==0) && (cached
=dirAddEntry(parentInode
, file
, &fileInode
->u
.inode
->inode_block
,
259 inodeUpdateTime(parentInode
);
260 cached
->flags
|=CACHE_FLAG_DIRTY
;
266 cacheAdd(parentInode
);
267 if ((result
==0) && freeSlot
&& fileInode
)
270 // dprintf("ps2fs: Setup file slot sizes\n");
272 freeSlot
->clink
=fileInode
;
273 if (openFlags
& O_APPEND
)
274 freeSlot
->position
= fileInode
->u
.inode
->size
;
276 freeSlot
->position
= 0;
278 result
=blockInitPos(freeSlot
->clink
, &freeSlot
->block_pos
, freeSlot
->position
);
281 if ((openFlags
& O_WRONLY
) &&
282 (fileInode
->u
.inode
->attr
& FIO_ATTR_CLOSED
)){
283 fileInode
->u
.inode
->attr
&= ~FIO_ATTR_CLOSED
;
284 fileInode
->flags
|= CACHE_FLAG_DIRTY
;
285 if (pfsMount
->flags
& FIO_ATTR_WRITEABLE
)
286 cacheFlushAllDirty(pfsMount
);
288 if ((result
=checkForLastError(pfsMount
, result
))==0)
291 freeSlot
->clink
=NULL
;
294 if(fileInode
) cacheAdd(fileInode
);
296 return checkForLastError(pfsMount
, result
);
299 // Reads unaligned data, or remainder data (size < 512)
300 int fileTransferRemainder(pfs_file_slot_t
*fileSlot
, void *buf
, int size
, int operation
)
304 pfs_blockpos_t
*blockpos
= &fileSlot
->block_pos
;
305 pfs_mount_t
*pfsMount
= fileSlot
->clink
->pfsMount
;
306 pfs_restsInfo_t
*info
= &fileSlot
->restsInfo
;
307 pfs_blockinfo
*bi
= blockGetCurrent(blockpos
);
309 sector
= ((bi
->number
+blockpos
->block_offset
) << pfsMount
->sector_scale
) +
310 (blockpos
->byte_offset
>> 9);
311 pos
= blockpos
->byte_offset
& 0x1FF;
313 if((info
->sector
!= sector
) || (info
->sub
!=bi
->subpart
))
315 if (fileSlot
->restsInfo
.dirty
)
317 result
=pfsMount
->blockDev
->transfer(pfsMount
->fd
, fileSlot
->restsBuffer
, info
->sub
, info
->sector
, 1, 1);
320 fileSlot
->restsInfo
.dirty
=0;
323 info
->sub
=bi
->subpart
;
326 if(pos
|| (fileSlot
->position
!= fileSlot
->clink
->u
.inode
->size
))
328 result
= pfsMount
->blockDev
->transfer(pfsMount
->fd
, fileSlot
->restsBuffer
, info
->sub
, info
->sector
, 1, 0);
330 return result
| 0x10000;
335 memcpy(buf
, fileSlot
->restsBuffer
+pos
, size
=min(size
, 512-(int)pos
));
337 memcpy(fileSlot
->restsBuffer
+pos
, buf
, size
=min(size
, 512-(int)pos
));
341 if (pfsMount
->flags
& FIO_ATTR_WRITEABLE
)
343 if ((result
=pfsMount
->blockDev
->transfer(pfsMount
->fd
, fileSlot
->restsBuffer
, info
->sub
,
344 info
->sector
, operation
, operation
)))
348 info
->dirty
=operation
;
353 // Does actual read/write of data from file
354 int fileTransfer(pfs_file_slot_t
*fileSlot
, u8
*buf
, int size
, int operation
)
357 pfs_blockpos_t
*blockpos
=&fileSlot
->block_pos
;
358 pfs_mount_t
*pfsMount
=fileSlot
->clink
->pfsMount
;
362 // dprintf2("ps2fs CALL: fileTransfer( , ,%d,%d)\n", size, operation);
364 // If we're writing and there is less free space in the last allocated block segment
365 // than can hold the data being written, then try and expand the block segment
366 if ((operation
==1) &&
367 (fileSlot
->clink
->u
.inode
->number_data
- 1 == blockpos
->block_segment
))
369 bytes_remain
= (blockGetCurrent(blockpos
)->count
- blockpos
->block_offset
) * pfsMount
->zsize
- blockpos
->byte_offset
;//u32
371 if (bytes_remain
< size
)
373 blockExpandSegment(fileSlot
->clink
, blockpos
,
374 ((size
-bytes_remain
+pfsMount
->zsize
-1) & (~(pfsMount
->zsize
-1))) / pfsMount
->zsize
);
383 // Get block info for current file position
384 bi
=blockGetCurrent(blockpos
);
386 // Get amount of remaining data in current block
387 bytes_remain
=(bi
->count
- blockpos
->block_offset
) * pfsMount
->zsize
- blockpos
->byte_offset
;
389 // If there is no space/data left in the current block segment, then we need to move onto the next
392 // If we're at the end of allocated block segments, then allocate a new block segment
393 if (blockpos
->block_segment
== fileSlot
->clink
->u
.inode
->number_data
-1){
395 printf("ps2fs: Panic: This is a bug!\n");
399 result
= blockAllocNewSegment(fileSlot
->clink
, blockpos
,
400 (size
- 1 + pfsMount
->zsize
) / pfsMount
->zsize
);
404 // Otherwise, move to the next block segment
406 if ((result
=blockSeekNextSegment(fileSlot
->clink
, blockpos
)))
408 dprintf("ps2fs: Failed to seek to next block segment!\n");
412 bi
=blockGetCurrent(blockpos
);
413 bytes_remain
=(bi
->count
- blockpos
->block_offset
) * pfsMount
->zsize
- blockpos
->byte_offset
;
418 printf("ps2fs: Panic: There is no zone.\n");
422 // If we are transferring size not a multiple of 512, under 512, or to
423 // an unaligned buffer we need to use a special function rather than
424 // just doing a ATA sector transfer.
425 if ((blockpos
->byte_offset
& 0x1FF) || (size
< 512) || ((u32
)buf
& 3))
427 dprintf("ps2fs: Transfer unaligned (size = %d, op = %d)\n", size
, operation
);
428 if ((result
=fileTransferRemainder(fileSlot
, buf
, size
, operation
)) < 0)
433 sectors
= bytes_remain
/ 512;
434 if ((size
/ 512) < sectors
) sectors
= size
/ 512; //sectors=min(size/512, sectors)
436 // Do the ATA sector transfer
437 result
=pfsMount
->blockDev
->transfer(pfsMount
->fd
, buf
, bi
->subpart
,
438 ((bi
->number
+ blockpos
->block_offset
) << pfsMount
->sector_scale
)+(blockpos
->byte_offset
/ 512),
442 result
|= 0x10000; // TODO: EIO define
445 result
= sectors
* 512;
449 fileSlot
->position
+= result
;
453 // If file has grown, need to mark inode as dirty
454 if(fileSlot
->clink
->u
.inode
->size
< fileSlot
->position
)
456 fileSlot
->clink
->u
.inode
->size
= fileSlot
->position
;
457 fileSlot
->clink
->flags
|= CACHE_FLAG_DIRTY
;
460 blockpos
->block_offset
+=blockSyncPos(blockpos
, result
);
462 return result
< 0 ? result
: total
;
465 void pfsPowerOffHandler(void* data
)
467 printf("pfs close all\n");
471 int pfsInit(iop_device_t
*f
)
480 pfsFioSema
= CreateSema(&sema
);
482 AddPowerOffHandler(pfsPowerOffHandler
, 0);
486 int pfsDeinit(iop_device_t
*f
)
490 DeleteSema(pfsFioSema
);
495 int pfsFormat(iop_file_t
*t
, const char *dev
, const char *blockdev
, void *args
, size_t arglen
)
497 int *arg
= (int *)args
;
500 block_device
*blockDev
;
503 // Has a fragment bit pattern been specified ?
504 if((arglen
== (3 * sizeof(int))) && (arg
[1] == 0x2D66))
507 if((blockDev
= getDeviceTable(blockdev
)) == 0)
510 WaitSema(pfsFioSema
);
512 fd
= open(blockdev
, O_RDWR
, 0644);
514 dprintf("ps2fs: Format: fragment = 0x%X\n", fragment
);
519 rv
= _format(blockDev
, fd
, arg
[0], fragment
);
523 SignalSema(pfsFioSema
);
528 int pfsOpen(iop_file_t
*f
, const char *name
, int flags
, int mode
)
532 pfs_file_slot_t
*freeSlot
;
533 pfs_mount_t
*pfsMount
;
538 if(!(pfsMount
= fioGetMountedUnit(f
->unit
)))
540 dprintf("Couldnt get mounted unit!\n");
544 // Find free file slot
545 for(i
= 0; i
< pfsConfig
.maxOpen
; i
++)
547 if(!fileSlots
[i
].fd
) {
548 freeSlot
= &fileSlots
[i
];
549 goto pfsOpen_slotFound
;
553 printf("ps2fs: Error: There are no free file slots!\n");
564 if((rv
= openFile(pfsMount
, freeSlot
, name
, f
->mode
, (mode
& 0xfff) | FIO_S_IFREG
)))
567 dprintf("ps2fs: File opened successfully!\n");
570 f
->privdata
= freeSlot
;
574 SignalSema(pfsFioSema
);
579 int pfsClose(iop_file_t
*f
)
581 pfs_file_slot_t
*fileSlot
= (pfs_file_slot_t
*)f
->privdata
;
584 rv
= checkFileSlot(fileSlot
);
588 closeFileSlot(fileSlot
);
590 SignalSema(pfsFioSema
);
595 int pfsRead(iop_file_t
*f
, void *buf
, int size
)
597 pfs_file_slot_t
*fileSlot
= (pfs_file_slot_t
*)f
->privdata
;
598 int result
= checkFileSlot(fileSlot
);
602 dprintf("ps2fs: bad file slot on read\n");
606 // Check bounds, adjust size if necessary
607 if(fileSlot
->clink
->u
.inode
->size
< (fileSlot
->position
+ size
))
608 size
= fileSlot
->clink
->u
.inode
->size
- fileSlot
->position
;
610 result
= size
? fileTransfer(fileSlot
, buf
, size
, 0) : 0;
611 result
= checkForLastError(fileSlot
->clink
->pfsMount
, result
);
613 SignalSema(pfsFioSema
);
617 int pfsWrite(iop_file_t
*f
, void *buf
, int size
)
619 pfs_mount_t
*pfsMount
;
620 pfs_file_slot_t
*fileSlot
= (pfs_file_slot_t
*)f
->privdata
;
621 int result
= checkFileSlot(fileSlot
);
626 pfsMount
= fileSlot
->clink
->pfsMount
;
628 result
= fileTransfer(fileSlot
, buf
, size
, 1);
630 if (pfsMount
->flags
& FIO_ATTR_WRITEABLE
)
631 cacheFlushAllDirty(pfsMount
);
633 result
= checkForLastError(pfsMount
, result
);
634 SignalSema(pfsFioSema
);
638 s64
_seek(pfs_file_slot_t
*fileSlot
, s64 offset
, int whence
, int mode
)
641 s64 startPos
, newPos
;
643 if (mode
& O_DIROPEN
)
645 dprintf("ps2fs: Cant seek: directory\n");
655 startPos
= fileSlot
->position
;
658 startPos
= fileSlot
->clink
->u
.inode
->size
;
663 newPos
= startPos
+ offset
;
665 if (((offset
< 0) && (startPos
< newPos
)) ||
666 ((offset
> 0) && (startPos
> newPos
)) ||
667 (fileSlot
->clink
->u
.inode
->size
< newPos
))
669 dprintf("ps2fs: Cant seek: invalid args\n");
673 cacheAdd(fileSlot
->block_pos
.inode
);
674 rv
=blockInitPos(fileSlot
->clink
, &fileSlot
->block_pos
, newPos
);
676 fileSlot
->position
= newPos
;
678 fileSlot
->position
= 0;
679 blockInitPos(fileSlot
->clink
, &fileSlot
->block_pos
, 0);
684 dprintf("ps2fs: Cant seek: failed to blockInitPos\n");
688 dprintf("ps2fs: Seek successfull! newPos = %ld\n", (u32
)newPos
);
693 int pfsLseek(iop_file_t
*f
, unsigned long pos
, int whence
)
695 pfs_file_slot_t
*fileSlot
= (pfs_file_slot_t
*)f
->privdata
;
696 int result
= checkFileSlot(fileSlot
);
701 result
= (u32
)_seek(fileSlot
, (s64
)pos
, whence
, f
->mode
);
703 SignalSema(pfsFioSema
);
707 s64
pfsLseek64(iop_file_t
*f
, s64 offset
, int whence
)
709 printf("ps2fs: Error: Operation currently unsupported.\n");
713 /*pfs_file_slot_t *fileSlot = (pfs_file_slot_t *)f->privdata;
716 rv=checkFileSlot(fileSlot);
719 rv=_seek(fileSlot, offset, whence, f->mode);
720 SignalSema(pfsFioSema);
725 int _remove(pfs_mount_t
*pfsMount
, const char *path
, int mode
)
732 if((parent
=inodeGetParent(pfsMount
, NULL
, path
, szPath
, &rv
))==NULL
)
735 if((file
=inodeGetFileInDir(parent
, szPath
, &rv
))!=NULL
)
739 if((file
->u
.inode
->mode
& FIO_S_IFMT
) != FIO_S_IFDIR
)
741 else if(checkDirForFiles(file
)==0)
743 else if(((u16
)file
->u
.inode
->inode_block
.number
==pfsMount
->root_dir
.number
) &&
744 ((u16
)file
->u
.inode
->inode_block
.subpart
==pfsMount
->root_dir
.subpart
))
746 else if(((u16
)file
->u
.inode
->inode_block
.number
==pfsMount
->current_dir
.number
) &&
747 ((u16
)file
->u
.inode
->inode_block
.subpart
==pfsMount
->current_dir
.subpart
))
751 if((file
->u
.inode
->mode
& FIO_S_IFMT
)==FIO_S_IFDIR
)
756 if(file
->u
.inode
->uid
!=0)
757 rv
=checkAccess(file
, 2);
761 return inodeRemove(parent
, file
, szPath
);
766 return checkForLastError(pfsMount
, rv
);
770 int pfsRemove(iop_file_t
*f
, const char *name
)
772 pfs_mount_t
*pfsMount
;
775 if(!(pfsMount
= fioGetMountedUnit(f
->unit
)))
778 rv
= _remove(pfsMount
, name
, 0);
780 SignalSema(pfsFioSema
);
785 int pfsMkdir(iop_file_t
*f
, const char *path
, int mode
)
787 pfs_mount_t
*pfsMount
;
790 mode
= (mode
& 0xfff) | 0x10000 | FIO_S_IFDIR
; // TODO: change to some constant/macro
792 if(!(pfsMount
= fioGetMountedUnit(f
->unit
)))
795 rv
= openFile(pfsMount
, NULL
, path
, O_CREAT
| O_WRONLY
, mode
);
797 SignalSema(pfsFioSema
);
802 int pfsRmdir(iop_file_t
*f
, const char *path
)
804 pfs_mount_t
*pfsMount
;
808 temp
= path
+ strlen(path
);
812 if(!(pfsMount
= fioGetMountedUnit(f
->unit
)))
815 rv
= _remove(pfsMount
, path
, 0x01); // TODO: constant for 0x01 ?
817 SignalSema(pfsFioSema
);
822 int pfsDopen(iop_file_t
*f
, const char *name
)
824 return pfsOpen(f
, name
, 0, 0);
827 int pfsDread(iop_file_t
*f
, iox_dirent_t
*dirent
)
829 pfs_file_slot_t
*fileSlot
= (pfs_file_slot_t
*)f
->privdata
;
830 pfs_mount_t
*pfsMount
;
836 // dprintf2("ps2fs CALL: pfsDread();\n");
838 rv
= checkFileSlot(fileSlot
);
842 pfsMount
= fileSlot
->clink
->pfsMount
;
844 if((fileSlot
->clink
->u
.inode
->mode
& FIO_S_IFMT
) != FIO_S_IFDIR
)
846 dprintf("ps2fs: dread error: not directory!\n");
850 if((rv
= getNextDentry(fileSlot
->clink
, &fileSlot
->block_pos
, (u32
*)&fileSlot
->position
,
851 dirent
->name
, &bi
)) > 0)
854 clink
= inodeGetData(pfsMount
, bi
.subpart
, bi
.number
, &result
);
857 fioStatFiller(clink
, &dirent
->stat
);
865 rv
= checkForLastError(pfsMount
, rv
);
866 SignalSema(pfsFioSema
);
871 void fioStatFiller(pfs_cache_t
*clink
, iox_stat_t
*stat
)
873 stat
->mode
= clink
->u
.inode
->mode
;
874 stat
->attr
= clink
->u
.inode
->attr
;
875 stat
->size
= (u32
)clink
->u
.inode
->size
;
876 stat
->hisize
= (u32
)(clink
->u
.inode
->size
>> 32);
877 memcpy(&stat
->ctime
, &clink
->u
.inode
->ctime
, sizeof(pfs_datetime
));
878 memcpy(&stat
->atime
, &clink
->u
.inode
->atime
, sizeof(pfs_datetime
));
879 memcpy(&stat
->mtime
, &clink
->u
.inode
->mtime
, sizeof(pfs_datetime
));
880 stat
->private_0
= clink
->u
.inode
->uid
;
881 stat
->private_1
= clink
->u
.inode
->gid
;
882 stat
->private_2
= clink
->u
.inode
->number_blocks
;
883 stat
->private_3
= clink
->u
.inode
->number_data
;
888 int pfsGetstat(iop_file_t
*f
, const char *name
, iox_stat_t
*stat
)
890 pfs_mount_t
*pfsMount
;
894 if(!(pfsMount
= fioGetMountedUnit(f
->unit
)))
897 clink
=inodeGetFile(pfsMount
, NULL
, name
, &rv
);
900 fioStatFiller(clink
, stat
);
904 SignalSema(pfsFioSema
);
905 return checkForLastError(pfsMount
, rv
);
908 int pfsChstat(iop_file_t
*f
, const char *name
, iox_stat_t
*stat
, unsigned int statmask
)
910 pfs_mount_t
*pfsMount
;
914 if(!(pfsMount
= fioGetMountedUnit(f
->unit
)))
917 clink
= inodeGetFile(pfsMount
, NULL
, name
, &rv
);
920 rv
= checkAccess(clink
, 0x02);
923 clink
->flags
|= 0x01;
925 if((statmask
& FIO_CST_MODE
) && ((clink
->u
.inode
->mode
& FIO_S_IFMT
) != FIO_S_IFLNK
))
926 clink
->u
.inode
->mode
= (clink
->u
.inode
->mode
& FIO_S_IFMT
) | (stat
->mode
& 0xfff);
927 if(statmask
& FIO_CST_ATTR
)
928 clink
->u
.inode
->attr
= (clink
->u
.inode
->attr
& 0xA0) | (stat
->attr
& 0xFF5F);
929 if(statmask
& FIO_CST_SIZE
)
931 if(statmask
& FIO_CST_CT
)
932 memcpy(&clink
->u
.inode
->ctime
, stat
->ctime
, sizeof(pfs_datetime
));
933 if(statmask
& FIO_CST_AT
)
934 memcpy(&clink
->u
.inode
->atime
, stat
->atime
, sizeof(pfs_datetime
));
935 if(statmask
& FIO_CST_MT
)
936 memcpy(&clink
->u
.inode
->mtime
, stat
->mtime
, sizeof(pfs_datetime
));
937 if(statmask
& FIO_CST_PRVT
) {
938 clink
->u
.inode
->uid
= stat
->private_0
;
939 clink
->u
.inode
->gid
= stat
->private_1
;
942 if(pfsMount
->flags
& FIO_ATTR_WRITEABLE
)
943 cacheFlushAllDirty(pfsMount
);
950 SignalSema(pfsFioSema
);
951 return checkForLastError(pfsMount
, rv
);
954 int pfsRename(iop_file_t
*ff
, const char *old
, const char *new)
956 char path1
[256], path2
[256];
958 pfs_mount_t
*pfsMount
;
960 pfs_cache_t
*parentOld
=NULL
, *parentNew
=NULL
;
961 pfs_cache_t
*removeOld
=NULL
, *removeNew
=NULL
;
962 pfs_cache_t
*iFileOld
=NULL
, *iFileNew
=NULL
;
963 pfs_cache_t
*newParent
=NULL
,*addNew
=NULL
;
965 pfsMount
=fioGetMountedUnit(ff
->unit
);
966 if (pfsMount
==0) return -ENODEV
;
968 parentOld
=inodeGetParent(pfsMount
, NULL
, old
, path1
, &result
);
970 u32 nused
=parentOld
->nused
;
977 if ((iFileOld
=inodeGetFileInDir(parentOld
, path1
, &result
))==0) goto exit
;
979 if ((parentNew
=inodeGetParent(pfsMount
, NULL
, new, path2
, &result
))==0) goto exit
;
981 f
=(iFileOld
->u
.inode
->mode
& FIO_S_IFMT
) == FIO_S_IFDIR
;
983 if ((parentNew
->nused
!= nused
) && ((parentOld
!=parentNew
) || (parentNew
->nused
!=2))){
988 iFileNew
=inodeGetFileInDir(parentNew
, path2
, &result
);
991 if ((iFileNew
->u
.inode
->mode
& FIO_S_IFMT
) != FIO_S_IFDIR
)
994 if (checkDirForFiles(iFileNew
)){
995 if (iFileNew
->nused
>= 2)
998 if (iFileOld
==iFileNew
)
1004 if ((iFileNew
->u
.inode
->mode
& FIO_S_IFMT
) == FIO_S_IFDIR
)
1007 if (iFileNew
->nused
>= 2)
1010 if (iFileOld
==iFileNew
)
1014 if (result
==-ENOENT
)
1017 if (result
) goto exit
;
1019 if (f
&& (parentOld
!=parentNew
)){
1020 pfs_cache_t
*parent
;
1022 parent
=cacheUsedAdd(parentNew
);
1026 if (parent
==iFileOld
){
1030 tmp
=inodeGetFileInDir(parent
, "..", &result
);
1032 if (tmp
==parent
)break;
1039 if (strcmp(path1
, ".") && strcmp(path1
, "..") &&
1040 strcmp(path2
, ".") && strcmp(path2
, "..")){
1041 result
=checkAccess(parentOld
, 3);
1043 result
=checkAccess(parentNew
, 3);
1048 if (iFileNew
&& ((removeNew
=dirRemoveEntry(parentNew
, path2
))==NULL
))
1051 removeOld
=dirRemoveEntry(parentOld
, path1
);
1055 addNew
=dirAddEntry(parentNew
, path2
, &iFileOld
->u
.inode
->inode_block
, iFileOld
->u
.inode
->mode
, &result
);
1056 if (addNew
&& f
&& (parentOld
!=parentNew
))
1057 newParent
=setParent(iFileOld
, &parentNew
->u
.inode
->inode_block
, &result
);
1064 if (removeNew
) removeNew
->pfsMount
=NULL
;
1065 if (removeOld
) removeOld
->pfsMount
=NULL
;
1066 if (addNew
) addNew
->pfsMount
=NULL
;
1067 if (iFileNew
) iFileNew
->pfsMount
=NULL
;
1068 parentOld
->pfsMount
=NULL
;
1069 parentNew
->pfsMount
=NULL
;
1071 if (parentOld
==parentNew
){
1072 if (removeOld
!=addNew
)
1073 removeOld
->flags
|= CACHE_FLAG_DIRTY
;
1076 inodeUpdateTime(parentOld
);
1077 removeOld
->flags
|=CACHE_FLAG_DIRTY
;
1079 inodeUpdateTime(parentNew
);
1080 addNew
->flags
|=CACHE_FLAG_DIRTY
;
1083 inodeUpdateTime(iFileOld
);
1084 newParent
->flags
|=CACHE_FLAG_DIRTY
;
1085 cacheAdd(newParent
);
1089 iFileNew
->flags
&= ~CACHE_FLAG_DIRTY
;
1090 bitmapFreeInodeBlocks(iFileNew
);
1093 if (pfsMount
->flags
& FIO_ATTR_WRITEABLE
)
1094 cacheFlushAllDirty(pfsMount
);
1096 if (removeOld
) cacheAdd(removeOld
);
1097 if (addNew
) cacheAdd(addNew
);
1098 if (removeNew
) cacheAdd(removeNew
);
1100 if (iFileNew
) cacheAdd(iFileNew
);
1102 cacheAdd(parentOld
);
1103 cacheAdd(parentNew
);
1105 SignalSema(pfsFioSema
);
1106 return checkForLastError(pfsMount
, result
);
1109 int pfsChdir(iop_file_t
*f
, const char *name
)
1111 pfs_mount_t
*pfsMount
;
1115 if(!(pfsMount
= fioGetMountedUnit(f
->unit
)))
1118 clink
= inodeGetFile(pfsMount
, 0, name
, &result
);
1120 if((clink
->u
.inode
->mode
& FIO_S_IFMT
) != FIO_S_IFDIR
)
1124 result
= checkAccess(clink
, 0x01);
1127 memcpy(&pfsMount
->current_dir
, &clink
->u
.inode
->inode_block
, sizeof(pfs_blockinfo
));
1133 SignalSema(pfsFioSema
);
1134 return checkForLastError(pfsMount
, result
);
1140 for(i
=0;i
<pfsConfig
.maxOpen
;i
++)
1142 pfs_restsInfo_t
*info
=&fileSlots
[i
].restsInfo
;
1144 pfs_mount_t
*pfsMount
=fileSlots
[i
].clink
->pfsMount
;
1145 pfsMount
->blockDev
->transfer(pfsMount
->fd
, &fileSlots
[i
].restsBuffer
,
1146 info
->sub
, info
->sector
, 1, IOCTL2_TMODE_WRITE
);
1147 fileSlots
[i
].restsInfo
.dirty
=0;
1152 int pfsSync(iop_file_t
*f
, const char *dev
, int flag
)
1154 pfs_mount_t
*pfsMount
;
1156 if(!(pfsMount
= fioGetMountedUnit(f
->unit
)))
1160 cacheFlushAllDirty(pfsMount
);
1161 hddFlushCache(pfsMount
->fd
);
1163 SignalSema(pfsFioSema
);
1164 return checkForLastError(pfsMount
, 0);
1167 int pfsMount(iop_file_t
*f
, const char *fsname
, const char *devname
, int flag
, void *arg
, size_t arglen
)
1171 block_device
*blockDev
;
1173 if(!(blockDev
= getDeviceTable(devname
)))
1176 WaitSema(pfsFioSema
);
1178 fd
= open(devname
, (flag
& O_RDONLY
) ? O_RDONLY
: O_RDWR
, 0644); // ps2hdd.irx fd
1182 dprintf("ps2fs: Mounting device..\n");
1183 if((rv
=mountDevice(blockDev
, fd
, f
->unit
, flag
)) < 0)
1186 SignalSema(pfsFioSema
);
1190 void _umount(pfs_mount_t
*pfsMount
)
1194 cacheFlushAllDirty(pfsMount
);
1195 for(i
=1; i
< numBuffers
+1;i
++){
1196 if(cacheBuf
[i
].pfsMount
==pfsMount
)
1197 cacheBuf
[i
].pfsMount
=NULL
;
1200 hddFlushCache(pfsMount
->fd
);
1203 int pfsUmount(iop_file_t
*f
, const char *fsname
)
1208 pfs_mount_t
*pfsMount
;
1210 if((pfsMount
= fioGetMountedUnit(f
->unit
))==NULL
)
1213 for(i
= 0; i
< pfsConfig
.maxOpen
; i
++)
1215 if((fileSlots
[i
].clink
!=NULL
) && (fileSlots
[i
].clink
->pfsMount
==pfsMount
))
1224 close(pfsMount
->fd
);
1225 clearMount(pfsMount
);
1228 rv
=-EBUSY
; // Mount device busy
1230 SignalSema(pfsFioSema
);
1234 int pfsSymlink(iop_file_t
*f
, const char *old
, const char *new)
1237 pfs_mount_t
*pfsMount
;
1240 if(old
==NULL
|| new==NULL
)
1243 if(!(pfsMount
=fioGetMountedUnit(f
->unit
)))
1246 rv
= openFile(pfsMount
, (pfs_file_slot_t
*)old
, (const char *)new, O_CREAT
|O_WRONLY
, mode
);
1247 SignalSema(pfsFioSema
);
1251 int pfsReadlink(iop_file_t
*f
, const char *path
, char *buf
, int buflen
)
1254 pfs_mount_t
*pfsMount
;
1259 if(!(pfsMount
=fioGetMountedUnit(f
->unit
)))
1262 if((clink
=inodeGetFile(pfsMount
, NULL
, path
, &rv
))!=NULL
)
1264 if((clink
->u
.inode
->mode
& FIO_S_IFMT
) == FIO_S_IFLNK
)
1268 rv
=strlen((char *)&clink
->u
.inode
->data
[1]);
1271 memcpy(buf
, &clink
->u
.inode
->data
[1], rv
);
1275 SignalSema(pfsFioSema
);
1277 return checkForLastError(pfsMount
, rv
);
1280 int pfsUnsupported()
1282 printf("ps2fs: Error: Operation currently unsupported.\n");