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_fioctl.c 577 2004-09-14 14:41:46Z pixel $
11 # PFS ioctl and devctl related routines
16 int pfsIoctl(iop_file_t
*f
, unsigned long arg
, void *param
)
21 int pfsDevctl(iop_file_t
*f
, const char *name
, int cmd
, void *arg
, size_t arglen
, void *buf
, size_t buflen
)
23 pfs_mount_t
*pfsMount
;
26 if(!(pfsMount
=fioGetMountedUnit(f
->unit
)))
31 case PFS_DEVCTL_GET_ZONE_SIZE
:
35 case PFS_DEVCTL_GET_ZONE_FREE
:
39 case PFS_DEVCTL_CLOSE_ALL
:
41 hddFlushCache(pfsMount
->fd
);
44 case PFS_DEVCTL_CLEAR_STAT
:
45 rv
=devctlFsckStat(pfsMount
, MODE_REMOVE_FLAG
);
48 case PFS_DEVCTL_GET_STAT
:
49 rv
=devctlFsckStat(pfsMount
, MODE_CHECK_FLAG
);
52 case PFS_DEVCTL_SET_UID
:
53 pfsMount
->uid
=*(u16
*)(arg
);
56 case PFS_DEVCTL_SET_GID
:
57 pfsMount
->gid
=*(u16
*)(arg
);
60 case PFS_DEVCTL_SHOW_BITMAP
:
69 SignalSema(pfsFioSema
);
74 int pfsIoctl2(iop_file_t
*f
, int cmd
, void *arg
, size_t arglen
, void *buf
, size_t buflen
)
77 pfs_file_slot_t
*fileSlot
= (pfs_file_slot_t
*)f
->privdata
;
78 pfs_mount_t
*pfsMount
;
80 if(f
->mode
& O_DIROPEN
)
81 if(cmd
==PFS_IOCTL2_ATTR_READ
)
84 if(!(f
->mode
& O_WRONLY
)) {
85 if(cmd
!=PFS_IOCTL2_ATTR_LOOKUP
)
86 if(cmd
!=PFS_IOCTL2_ATTR_READ
)
89 if((rv
=checkFileSlot(fileSlot
))<0)
91 pfsMount
=fileSlot
->clink
->pfsMount
;
95 case PFS_IOCTL2_MALLOC
:
96 rv
=ioctl2Alloc(fileSlot
->clink
, *(int *)(arg
), 1);
100 ioctl2Free(fileSlot
->clink
);
103 case PFS_IOCTL2_ATTR_ADD
:
104 case PFS_IOCTL2_ATTR_DEL
:
105 case PFS_IOCTL2_ATTR_LOOKUP
:
106 case PFS_IOCTL2_ATTR_READ
:
107 rv
=ioctl2Attr(fileSlot
->clink
, cmd
, arg
, buf
, &fileSlot
->aentryOffset
);
110 case PFS_IOCTL2_GET_INODE
:
111 memcpy(buf
, fileSlot
->clink
->u
.inode
, sizeof(pfs_inode
));
112 rv
= sizeof(pfs_inode
);
120 if(pfsMount
->flags
& FIO_ATTR_WRITEABLE
)
121 cacheFlushAllDirty(pfsMount
);
122 rv
=checkForLastError(pfsMount
, rv
);
123 SignalSema(pfsFioSema
);
128 int ioctl2Attr(pfs_cache_t
*clink
, int cmd
, void *arg
, void *outbuf
, u32
*offset
)
129 { // attr set, attr delete, attr lookup, attr read cmds
133 if((flink
=cacheGetData(clink
->pfsMount
, clink
->sub
, clink
->sector
+1
134 ,CACHE_FLAG_NOTHING
, &rv
))==NULL
)
139 case PFS_IOCTL2_ATTR_ADD
:
140 rv
=ioctl2AttrAdd(flink
, arg
);
143 case PFS_IOCTL2_ATTR_DEL
:
144 rv
=ioctl2AttrDelete(flink
, arg
);
147 case PFS_IOCTL2_ATTR_LOOKUP
:
148 rv
=ioctl2AttrLoopUp(flink
, arg
, outbuf
);
151 case PFS_IOCTL2_ATTR_READ
:
152 rv
=ioctl2AttrRead(flink
, outbuf
, offset
);
161 void devctlCloseAll()
165 for(i
=0;i
< pfsConfig
.maxOpen
;i
++)
168 closeFileSlot(&fileSlots
[i
]);
170 for(i
=0;i
< pfsConfig
.maxOpen
;i
++)
172 pfs_mount_t
*pfsMount
;
173 if((pfsMount
=getMountedUnit(i
))!=NULL
)
174 cacheFlushAllDirty(pfsMount
);
179 int devctlFsckStat(pfs_mount_t
*pfsMount
, int mode
)
184 if((clink
=cacheAllocClean(&rv
))!=NULL
){
185 rv
=fsckStat(pfsMount
, clink
->u
.superblock
, FSCK_STAT_ERROR_0x02
, mode
);
191 pfs_aentry_t
*getAentry(pfs_cache_t
*clink
, char *key
, char *value
, int mode
)
192 { // mode 0=lookup, 1=add, 2=delete
194 pfs_aentry_t
*aentry
=clink
->u
.aentry
;
195 pfs_aentry_t
*aentryLast
=NULL
;
199 fullsize
=(kLen
+strlen(value
)+7) & ~3;
200 for(end
=(u32
)aentry
+1024;(u32
)end
< (u32
)(aentry
); (char *)aentry
+=aentry
->aLen
)
203 printf("ps2fs: Error: attrib-entry allocated length/4 != 0\n");
204 if(aentry
->aLen
< ((aentry
->kLen
+aentry
->vLen
+7) & ~3))
206 printf("ps2fs: Panic: attrib-entry is too small\n");
209 if((u32
)end
< (u32
)aentry
+aentry
->aLen
)
210 printf("ps2fs: Error: attrib-emtru too big\n");
215 if(kLen
==aentry
->kLen
)
216 if(memcmp(key
, aentry
->str
, kLen
)==0)
223 if(aentry
->aLen
>=fullsize
)
226 if(aentry
->aLen
- ((aentry
->kLen
+aentry
->vLen
+7) & ~3) < fullsize
)
231 if(kLen
==aentry
->kLen
)
233 if(memcmp(key
, aentry
->str
, kLen
)==0)
237 aentryLast
->aLen
+=aentry
->aLen
;
254 int ioctl2AttrAdd(pfs_cache_t
*clink
, pfs_ioctl2attr_t
*attr
)
257 pfs_aentry_t
*aentry
;
261 kLen
=strlen(attr
->key
);
262 vLen
=strlen(attr
->value
);
263 if(kLen
>=256 || vLen
>=256) // max size safe e check
266 if(kLen
==0 || vLen
==0) // no input check
269 if(getAentry(clink
, attr
->key
, NULL
, 0))
271 if(!(aentry
=getAentry(clink
, attr
->key
, attr
->value
, 1)))
277 tmp
=aentry
->aLen
-((aentry
->kLen
+(aentry
->vLen
+ 7)) & ~3);
280 (char *)aentry
+=aentry
->aLen
;
284 memcpy(&aentry
->str
[0], attr
->key
, aentry
->kLen
);
285 memcpy(&aentry
->str
[aentry
->kLen
], attr
->value
, aentry
->vLen
);
286 clink
->flags
|=CACHE_FLAG_DIRTY
;
291 int ioctl2AttrDelete(pfs_cache_t
*clink
, void *arg
)
293 pfs_aentry_t
*aentry
;
295 if((aentry
=getAentry(clink
, arg
, 0, 2))==NULL
)
297 clink
->flags
|=CACHE_FLAG_DIRTY
;
301 int ioctl2AttrLoopUp(pfs_cache_t
*clink
, char *key
, char *value
)
303 pfs_aentry_t
*aentry
;
305 if((aentry
=getAentry(clink
, key
, 0, 0))){
306 memcpy(value
, &aentry
->str
[aentry
->kLen
], aentry
->vLen
);
307 value
[aentry
->vLen
]=0;
313 int ioctl2AttrRead(pfs_cache_t
*clink
, pfs_ioctl2attr_t
*attr
, u32
*offset
)
315 pfs_aentry_t
*aentry
;
320 aentry
=(pfs_aentry_t
*)((u32
)(clink
->u
.inode
)+*offset
);
321 memcpy(attr
->key
, &aentry
->str
[0], aentry
->kLen
);
322 attr
->key
[aentry
->kLen
]=0;
323 memcpy(attr
->value
, &aentry
->str
[aentry
->kLen
], aentry
->vLen
);
324 attr
->value
[aentry
->vLen
]=0;
325 *offset
+=aentry
->aLen
; // next
328 } while(*offset
< 1024);
334 int ioctl2Alloc(pfs_cache_t
*clink
, int msize
, int mode
)
336 pfs_blockpos_t blockpos
;
341 zsize
=clink
->pfsMount
->zsize
;
342 val
=((msize
-1 + zsize
) & (-zsize
)) / zsize
;
345 if (((clink
->u
.inode
->number_blocks
-clink
->u
.inode
->number_segdesg
) *(u64
)zsize
)
346 >= (clink
->u
.inode
->size
+ msize
))
349 if((blockpos
.inode
= blockGetLastSegmentDescriptorInode(clink
, &result
)))
351 blockpos
.block_offset
=blockpos
.byte_offset
=0;
352 blockpos
.block_segment
=clink
->u
.inode
->number_data
-1;
353 val
-=blockExpandSegment(clink
, &blockpos
, val
);
354 while (val
&& ((result
=blockAllocNewSegment(clink
, &blockpos
, val
))>=0)){
358 cacheAdd(blockpos
.inode
);
363 void ioctl2Free(pfs_cache_t
*pfree
)
367 pfs_mount_t
*pfsMount
= pfree
->pfsMount
;
368 pfs_inode
*inode
= pfree
->u
.inode
;
369 u32 nextsegdesc
= 1, limit
= inode
->number_data
, i
, j
= 0, zones
;
373 zones
= inode
->size
/ pfsMount
->zsize
;
374 if(inode
->size
% pfsMount
->zsize
)
376 if(inode
->number_segdesg
+ zones
== inode
->number_blocks
)
381 clink
= cacheUsedAdd(pfree
);
383 // iterate through each of the block segments used by the inode
384 for (i
= 1; i
< limit
&& j
; i
++)
388 if ((clink
= blockGetNextSegment(clink
, &result
)) == 0)
394 if(j
< clink
->u
.inode
->data
[fixIndex(i
)].count
)
396 clink
->u
.inode
->data
[fixIndex(i
)].count
-= j
;
397 b
.subpart
= clink
->u
.inode
->data
[fixIndex(i
)].subpart
;
399 b
.number
= clink
->u
.inode
->data
[fixIndex(i
)].number
+
400 clink
->u
.inode
->data
[fixIndex(i
)].count
;
402 clink
->flags
|= CACHE_FLAG_DIRTY
;
405 j
-= clink
->u
.inode
->data
[fixIndex(i
)].count
;
408 pfree
->u
.inode
->number_data
= i
;
409 pfree
->u
.inode
->number_blocks
= zones
+ nextsegdesc
;
410 pfree
->u
.inode
->number_segdesg
= nextsegdesc
;
411 pfree
->u
.inode
->last_segment
.number
= clink
->u
.inode
->data
[0].number
;
412 pfree
->u
.inode
->last_segment
.subpart
= clink
->u
.inode
->data
[0].subpart
;
413 pfree
->u
.inode
->last_segment
.count
= clink
->u
.inode
->data
[0].count
;
414 pfree
->flags
|= CACHE_FLAG_DIRTY
;
417 bitmapFreeBlockSegment(pfsMount
, &b
);
421 if (fixIndex(i
) == 0)
423 if((clink
= blockGetNextSegment(clink
, &result
)) == 0)
426 bi
= &clink
->u
.inode
->data
[fixIndex(i
++)];
427 bitmapFreeBlockSegment(pfsMount
, bi
);
428 cacheMarkClean(pfsMount
, bi
->subpart
, bi
->number
<<pfsMount
->inode_scale
,
429 (bi
->number
+bi
->count
)<<pfsMount
->inode_scale
);