PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
dir.c
1/*
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.
9#
10# PFS directory parsing routines
11*/
12
13#include <errno.h>
14#include <stdio.h>
15#ifdef _IOP
16#include <sysclib.h>
17#else
18#include <string.h>
19#endif
20#include <iomanX.h>
21
22#include "libpfs.h"
23
24extern u32 pfsMetaSize;
25
26// Gets a dir entry from the inode specified by clink
27pfs_cache_t *pfsGetDentry(pfs_cache_t *clink, char *path, pfs_dentry_t **dentry, u32 *size, int option)
28{
29 pfs_blockpos_t block_pos;
30 pfs_dentry_t *d;
31 u16 aLen;
32 pfs_dentry_t *d2;
33 pfs_cache_t *dentCache;
34 u32 new_dentryLen=0,dentryLen;
35 int len=0, result;
36
37 if (path)
38 {
39 len = strlen(path);
40 new_dentryLen = (len+8+3) &~3;
41 }
42 *size = 0;
43
44 block_pos.inode = pfsCacheUsedAdd(clink);
45 block_pos.block_segment = 1;
46 block_pos.block_offset = 0;
47 block_pos.byte_offset = 0;
48 dentCache = pfsGetDentriesChunk(&block_pos, &result);
49
50 if (dentCache != NULL)
51 {
52 d2=d=dentCache->u.dentry;
53 while(*size < clink->u.inode->size)
54 {
55 // Read another dentry chunk if we need to
56 if (d2 >= (pfs_dentry_t*)((u8*)dentCache->u.inode + pfsMetaSize))
57 {
58 if (pfsInodeSync(&block_pos, pfsMetaSize, clink->u.inode->number_data))
59 break;
60 pfsCacheFree(dentCache);
61
62 if ((dentCache=pfsGetDentriesChunk(&block_pos, &result)) == NULL)
63 break;
64 d=dentCache->u.dentry;
65 }
66
67 // Scan through the sector.
68 for (d2=(pfs_dentry_t*)((u8*)d+512); d < d2; d=(pfs_dentry_t *)((u8*)d + aLen))
69 {
70 aLen=(d->aLen & 0xFFF);
71
72 if (aLen & 3){
73 PFS_PRINTF(PFS_DRV_NAME": Error: dentry allocated length/4 != 0\n");
74 goto _exit;
75 }
76 dentryLen = (d->pLen + 8 + 3) & 0x1FC;
77 if (aLen < dentryLen){
78 PFS_PRINTF(PFS_DRV_NAME": Error: dentry is too small\n");
79 goto _exit;
80 }
81 if (d2 < (pfs_dentry_t*)((u8*)d + aLen)){
82 PFS_PRINTF(PFS_DRV_NAME": Error: dentry across sectors\n");
83 goto _exit;
84 }
85
86 // decide if the current dentry meets the required criteria, based on 'option'
87 switch(option)
88 {
89 case 0: // result = 1 when paths are equal
90 result = (len==d->pLen) && (memcmp(path, d->path, d->pLen)==0);
91 break;
92 case 1: // result = 1 when either there is no inode or if there is enough space remaining in the inode.
93 result = ((d->inode) || (aLen < new_dentryLen)) ? (aLen - dentryLen
94 >= new_dentryLen) : 1;
95 break;
96 case 2: // result = 1 when dir path is not empty, "." or ".."
97 result = d->pLen && strcmp(d->path, ".") && strcmp(d->path, "..");
98 break;
99 default:
100 goto _exit;
101 }
102
103 if (result)
104 {
105 *dentry=d;
106 pfsCacheFree(block_pos.inode);
107 return dentCache;
108 }
109 *size+=aLen;
110 }
111 }
112_exit: pfsCacheFree(dentCache);
113 }
114 pfsCacheFree(block_pos.inode);
115 return NULL;
116}
117
118int pfsGetNextDentry(pfs_cache_t *clink, pfs_blockpos_t *blockpos, u32 *position, char *name, pfs_blockinfo_t *bi)
119{
120 int result;
121 pfs_dentry_t *dentry;
122 u32 len=0;
123
124 // loop until a non-empty entry is found or until the end of the dentry chunk is reached
125 while((len == 0) && (*position < clink->u.inode->size))
126 {
127 pfs_cache_t *dcache;
128
129 if (!(dcache=pfsGetDentriesChunk(blockpos, &result)))
130 {
131 PFS_PRINTF(PFS_DRV_NAME": couldnt get dentries chunk for dread!\n");
132 break;
133 }
134
135 dentry = (pfs_dentry_t*)((u8*)dcache->u.data + (blockpos->byte_offset % pfsMetaSize));
136
137 len = dentry->pLen;
138 memcpy(name, dentry->path, len);
139 name[len] = '\0';
140
141 bi->subpart = dentry->sub;
142 bi->number = dentry->inode;
143 pfsCacheFree(dcache);
144
145 *position += dentry->aLen & 0xFFF;
146
147 // update blockpos
148 if (pfsInodeSync(blockpos, dentry->aLen & 0xFFF, clink->u.inode->number_data))
149 break;
150 }
151
152 return len;
153}
154
155pfs_cache_t *pfsFillDentry(pfs_cache_t *clink, pfs_dentry_t *dentry, char *path1, pfs_blockinfo_t *bi, u32 len, u16 mode)
156{
157 dentry->inode=bi->number;
158 dentry->sub=(u8)bi->subpart;
159 dentry->pLen=strlen(path1);
160 dentry->aLen=len | (mode & FIO_S_IFMT);
161 memcpy(dentry->path, path1, dentry->pLen & 0xFF);
162
163 return clink;
164}
165
166pfs_cache_t *pfsDirAddEntry(pfs_cache_t *dir, char *filename, pfs_blockinfo_t *bi, u16 mode, int *result)
167{
168 pfs_dentry_t *dentry;
169 u32 size;
170 u32 len;
171 pfs_cache_t *dcache;
172
173 dcache=pfsGetDentry(dir, filename, &dentry, &size, 1);
174 if (dcache != NULL){
175 len=dentry->aLen & 0xFFF;
176 if (dentry->pLen)
177 len-=(dentry->pLen + 11) & 0x1FC;
178 dentry->aLen=(dentry->aLen & FIO_S_IFMT) | ((dentry->aLen & 0xFFF) - len);
179 dentry=(pfs_dentry_t *)((u8*)dentry + (dentry->aLen & 0xFFF));
180 }else{
181 int offset;
182
183 if ((*result=pfsAllocZones(dir, sizeof(pfs_dentry_t), 0))<0)
184 return NULL;
185 dcache=pfsGetDentriesAtPos(dir, dir->u.inode->size, &offset, result);
186 if (dcache==NULL)
187 return NULL;
188
189 dir->u.inode->size += sizeof(pfs_dentry_t);
190
191 dentry=(pfs_dentry_t*)((u8*)dcache->u.dentry+offset);
192 len=sizeof(pfs_dentry_t);
193 }
194 return pfsFillDentry(dcache, dentry, filename, bi, len, mode);
195}
196
197pfs_cache_t *pfsDirRemoveEntry(pfs_cache_t *clink, char *path)
198{
199 pfs_dentry_t *dentry;
200 u32 size;
201 u16 aLen;
202 pfs_dentry_t *dlast=NULL, *dnext;
203 pfs_cache_t *c;
204
205 if ((c=pfsGetDentry(clink, path, &dentry, &size, 0)) != NULL){
206 int i=0, val;
207
208 val=(u8*)dentry-(u8*)c->u.dentry;
209 if (val<0) val +=511;
210 val /=512;
211 val *=512;
212
213 dnext=(pfs_dentry_t*)((u8*)c->u.dentry+val);
214 do{
215 aLen = dnext->aLen & 0xFFF;
216
217 if (dnext==dentry){
218 if (dlast)
219 dlast->aLen=(dlast->aLen & FIO_S_IFMT) | ((dlast->aLen & 0xFFF) + aLen);
220 else{
221 dnext->inode=0;
222 dnext->pLen=0;
223
224 if (size+aLen >= clink->u.inode->size)
225 clink->u.inode->size -= aLen;
226 }
227 return c;
228 }
229 i+=aLen;
230 dlast=dnext;
231 dnext=(pfs_dentry_t *)((u8*)dnext + aLen);
232 }while (i<512);
233 }
234 return NULL;
235}
236
237int pfsCheckDirForFiles(pfs_cache_t *clink)
238{
239 pfs_dentry_t *dentry;
240 pfs_cache_t *dcache;
241 u32 size;
242
243 if((dcache=pfsGetDentry(clink, NULL, &dentry, &size, 2))){
244 pfsCacheFree(dcache);
245 return 0;
246 }
247 return 1;
248}
249
250void pfsFillSelfAndParentDentries(pfs_cache_t *clink, pfs_blockinfo_t *self, pfs_blockinfo_t *parent)
251{
252 pfs_dentry_t *dentry=clink->u.dentry;
253
254 memset(dentry, 0, pfsMetaSize);
255 dentry->inode=self->number;
256 dentry->path[0]='.';
257 dentry->path[1]='\0';
258 dentry->sub=(u8)self->subpart;
259 dentry->pLen=1;
260 dentry->aLen=12 | FIO_S_IFDIR;
261
262 dentry=(pfs_dentry_t *)((u8*)dentry + 12);
263
264 dentry->inode=parent->number;
265 dentry->path[0]='.';
266 dentry->path[1]='.';
267 dentry->path[2]='\0';
268 dentry->sub=(u8)parent->subpart;
269 dentry->pLen=2;
270 dentry->aLen=500 | FIO_S_IFDIR;
271}
272
273pfs_cache_t* pfsSetDentryParent(pfs_cache_t *clink, pfs_blockinfo_t *bi, int *result)
274{
275 int offset;
276 pfs_cache_t *dcache;
277
278 dcache=pfsGetDentriesAtPos(clink, 0, &offset, result);
279 if (dcache){
280 pfs_dentry_t *d=(pfs_dentry_t*)(12+(u8*)dcache->u.data);
281 d->inode=bi->number;
282 d->sub =(u8)bi->subpart;
283 }
284 return dcache;
285}
286
287// Returns the cached inode for the file (dir) in the directory pointed
288// to by the dir inode.
289pfs_cache_t *pfsInodeGetFileInDir(pfs_cache_t *dirInode, char *path, int *result)
290{
291 pfs_dentry_t *dentry;
292 u32 size;
293 pfs_cache_t *clink;
294
295 if (path[0]==0)
296 return pfsCacheUsedAdd(dirInode);
297
298 // If we're in the root dir, don't do anything for ".."
299 if ((dirInode->block ==
300 dirInode->pfsMount->root_dir.number << dirInode->pfsMount->inode_scale) &&
301 (dirInode->sub == dirInode->pfsMount->root_dir.subpart) &&
302 (strcmp(path, "..") == 0))
303 return pfsCacheUsedAdd(dirInode);
304
305 if ((*result=pfsCheckAccess(dirInode, 1)) < 0)
306 return NULL;
307
308 // Get dentry of file/dir specified by path from the dir pointed to
309 // by the inode (dirInode). Then return the cached inode for that dentry.
310 if ((clink=pfsGetDentry(dirInode, path, &dentry, &size, 0))){
311 pfsCacheFree(clink);
312 return pfsInodeGetData(dirInode->pfsMount,
313 dentry->sub, dentry->inode, result);
314 }
315
316 *result=-ENOENT;
317 return NULL;
318}
319
320pfs_cache_t *pfsInodeGetFile(pfs_mount_t *pfsMount, pfs_cache_t *clink,
321 const char *name, int *result) {
322 char path[256];
323 pfs_cache_t *c;
324
325 c=pfsInodeGetParent(pfsMount, clink, name, path, result);
326 if (c){
327 pfs_cache_t *fileInode;
328
329 fileInode=pfsInodeGetFileInDir(c, path, result);
330 pfsCacheFree(c);
331 return fileInode;
332 }
333 return NULL;
334}
335
336void pfsInodeFill(pfs_cache_t *ci, pfs_blockinfo_t *bi, u16 mode, u16 uid, u16 gid)
337{
338 u32 val;
339
340 memset(ci->u.inode, 0, pfsMetaSize);
341
342 ci->u.inode->magic=PFS_SEGD_MAGIC;
343
344 ci->u.inode->inode_block.number=bi->number;
345 ci->u.inode->inode_block.subpart=bi->subpart;
346 ci->u.inode->inode_block.count=bi->count;
347
348 ci->u.inode->last_segment.number=bi->number;
349 ci->u.inode->last_segment.subpart=bi->subpart;
350 ci->u.inode->last_segment.count=bi->count;
351
352 ci->u.inode->mode=mode;
353 ci->u.inode->uid=uid;
354 ci->u.inode->gid=gid;
355
356 if ((mode & FIO_S_IFMT) == FIO_S_IFDIR){
357 ci->u.inode->attr=0xA0;
358 ci->u.inode->size=sizeof(pfs_dentry_t);
359 val=2;
360 }else{
361 ci->u.inode->size=0;
362 val=1;
363 }
364 ci->u.inode->number_data=val;
365 ci->u.inode->number_blocks=val;
366
367 pfsGetTime(&ci->u.inode->ctime);
368 memcpy(&ci->u.inode->atime, &ci->u.inode->ctime, sizeof(pfs_datetime_t));
369 memcpy(&ci->u.inode->mtime, &ci->u.inode->ctime, sizeof(pfs_datetime_t));
370
371 ci->u.inode->number_segdesg=1;
372 ci->u.inode->data[0].number =bi->number;
373 ci->u.inode->data[0].subpart=bi->subpart;
374 ci->u.inode->data[0].count =bi->count;
375
376 ci->u.inode->subpart=bi->subpart;
377
378 ci->flags |= PFS_CACHE_FLAG_DIRTY;
379}
380
381
382// Given a path, this function will return the inode for the directory which holds
383// the file (dir) specified by the filename.
384//
385// ie: if filename = /usr/local/ps2/games then it will return the inode for /usr/local/ps2
386pfs_cache_t* pfsInodeGetParent(pfs_mount_t *pfsMount, pfs_cache_t *clink, const char *filename,
387 char *path, int *result)
388{
389 static int pfsSymbolicLinks = 0;
390 pfs_cache_t *link, *inode;
391 char *filename2=(char*)filename;
392
393 if (filename2[0]==0)
394 {
395 *result=-ENOENT;
396 if (clink) pfsCacheFree(clink);
397 return NULL;
398 }
399
400 if (filename2[0] == '/')
401 {
402
403 // Get inode for root dir
404
405 if (clink) pfsCacheFree(clink);
406 if ((clink=pfsInodeGetData(pfsMount, pfsMount->root_dir.subpart,
407 pfsMount->root_dir.number, result))==0)
408 return NULL;
409 }
410 else if (clink==NULL)
411 {
412
413 // Otherwise if relative path, get inode for current dir
414
415 if ((clink=pfsInodeGetData(pfsMount, pfsMount->current_dir.subpart,
416 pfsMount->current_dir.number, result))==0)
417 return NULL;
418 }
419
420 do
421 {
422 filename2=pfsSplitPath(filename2, path, result);
423 if (filename2==NULL) return NULL;
424
425 // If we've reached the end of the path, then we want to return
426 // the cached inode for the directory which holds the file/dir in path
427 if (filename2[0]==0)
428 {
429 if ((clink->u.inode->mode & FIO_S_IFMT) == FIO_S_IFDIR)
430 return clink;
431
432 pfsCacheFree(clink);
433 *result=-ENOTDIR; // not a directory
434 return NULL;
435 }
436
437 inode=pfsInodeGetFileInDir(clink, path, result);
438
439 if (inode && ((inode->u.inode->mode & FIO_S_IFMT) == FIO_S_IFLNK))
440 {
441 if (pfsSymbolicLinks >= 4)
442 {
443 *result=-ELOOP; // too many symbolic links
444 pfsCacheFree(clink);
445 pfsCacheFree(inode);
446 return NULL;
447 }
448
449 pfsSymbolicLinks++;
450 link=pfsInodeGetFile(pfsMount, clink, (char*)&inode->u.inode->data[1], result);
451 pfsSymbolicLinks--;
452
453 clink=inode;
454 if (link==0)
455 {
456 pfsCacheFree(inode);
457 return NULL;
458 }
459 inode=link;
460 }
461 pfsCacheFree(clink);
462 clink=inode;
463
464 } while (inode);
465
466 return NULL;
467}
468
469int pfsInodeRemove(pfs_cache_t *parent, pfs_cache_t *inode, char *path)
470{
471 pfs_cache_t *entry;
472 int rv=0;
473
474 if((entry=pfsDirRemoveEntry(parent, path))!=NULL)
475 {
476 pfsInodeSetTimeParent(parent, entry);
477 pfsCacheFree(entry);
478 }
479 else
480 rv=-ENOENT;
481
482 pfsCacheFree(parent);
483 if(rv==0)
484 {
485 inode->flags&=~PFS_CACHE_FLAG_DIRTY;
486 pfsBitmapFreeInodeBlocks(inode);
487 //if(parent->pfsMount->flags & PFS_FIO_ATTR_WRITEABLE) //Not checked for in late versions of PFS.
488 pfsCacheFlushAllDirty(parent->pfsMount);
489 }
490
491 pfsCacheFree(inode);
492 return rv;
493}
494
495pfs_cache_t *pfsInodeCreate(pfs_cache_t *clink, u16 mode, u16 uid, u16 gid, int *result)
496{
497 pfs_blockinfo_t a, b;
498
499 pfs_mount_t *pfsMount=clink->pfsMount;
500 u32 j;
501 u32 i;
502 pfs_cache_t *inode;
503
504 if ((mode & FIO_S_IFMT) == FIO_S_IFDIR)
505 {
506 if (pfsMount->num_subs > clink->u.inode->subpart)
507 clink->u.inode->subpart++;
508 else
509 clink->u.inode->subpart=0;
510 a.number =0;
511 a.subpart=clink->u.inode->subpart;
512 j= (pfsMount->zfree * (u64)100) / pfsMount->total_zones;
513 i= (pfsMount->free_zone[a.subpart] * (u64)100) /
514 (pfsMount->blockDev->getSize(pfsMount->fd, a.subpart) >> pfsMount->sector_scale);
515 if ((i < j) && ((j-i) >= 11))
516 a.subpart=pfsGetMaxIndex(pfsMount);
517 }else{
518 a.number=clink->u.inode->inode_block.number;
519 a.subpart=clink->u.inode->inode_block.subpart;
520 }
521 a.count=1;
522
523 // Search for a free zone, starting from parent dir inode block
524 *result=pfsBitmapSearchFreeZone(pfsMount, &a, 2);
525 if (*result<0) return 0;
526 inode=pfsCacheGetData(pfsMount, a.subpart, a.number << pfsMount->inode_scale,
527 PFS_CACHE_FLAG_SEGD | PFS_CACHE_FLAG_NOLOAD, result);
528 if (inode == NULL)
529 return NULL;
530
531 // Initialise the inode (which has been allocate blocks specified by a)
532 pfsInodeFill(inode, (pfs_blockinfo_t*)&a, mode, uid, gid);
533 if ((mode & FIO_S_IFMT) != FIO_S_IFDIR)
534 return inode;
535
536 b.number=a.number;
537 b.subpart=a.subpart;
538 b.count=a.count;
539
540 *result=pfsBitmapSearchFreeZone(pfsMount, (pfs_blockinfo_t*)&a, 0);
541 if (*result<0){
542 pfsCacheFree(inode);
543 pfsBitmapFreeBlockSegment(pfsMount, (pfs_blockinfo_t*)&b);
544 return NULL;
545 }
546
547 inode->u.inode->data[1].number=a.number;
548 inode->u.inode->data[1].subpart=a.subpart;
549 inode->u.inode->data[1].count =a.count;
550
551 return inode;
552}
553
554int pfsCheckAccess(pfs_cache_t *clink, int flags)
555{
556 int mode;
557
558 // Bail if trying to write to read-only mount
559 if ((clink->pfsMount->flags & FIO_MT_RDONLY) && (flags & FIO_O_WRONLY))
560 return -EROFS;
561
562 if (((clink->u.inode->mode & FIO_S_IFMT) != FIO_S_IFDIR) &&
563 ((clink->u.inode->mode & 0111) == 0))
564 mode=6;
565 else
566 mode=7;
567 return ((mode & flags) & 7) == flags ? 0 : -EACCES;
568}
569
570char* pfsSplitPath(char *filename, char *path, int *result)
571{
572 int i=0;
573 int j=0;
574
575 for (i=0; filename[i] == '/'; i++)
576 ;
577
578 for (; i<1024 && filename[i] != '/'; i++){
579 if (filename[i] == 0) break;
580 if (j < 255)
581 path[j++] = filename[i];
582 }
583
584 if (j<256)
585 path[j]=0;
586
587 while (filename[i] == '/')
588 if (i<1024)
589 i++;
590 else
591 break;
592 if (i<1024)
593 return &filename[i];
594
595 *result=-ENAMETOOLONG;
596 return 0;
597}
598
599u16 pfsGetMaxIndex(pfs_mount_t *pfsMount)
600{
601 u32 max=0, maxI=0, i, v;
602
603 for (i=0; i < pfsMount->num_subs + 1; i++) //enumerate all subs
604 {
605 v = (pfsMount->free_zone[i] * (u64)100) /
606 (pfsMount->blockDev->getSize(pfsMount->fd, i) >> pfsMount->sector_scale);
607 if (max < v)
608 {
609 max=v;
610 maxI=i;
611 }
612 }
613 return maxI;
614}
615
616int pfsAllocZones(pfs_cache_t *clink, int msize, int mode)
617{
618 pfs_blockpos_t blockpos;
619 int result=0;
620 u32 val;
621 int zsize;
622
623 zsize=clink->pfsMount->zsize;
624 val=((msize-1 + zsize) & (-zsize)) / zsize;
625
626 if(mode==0)
627 if (((clink->u.inode->number_blocks-clink->u.inode->number_segdesg) *(u64)zsize)
628 >= (clink->u.inode->size + msize))
629 return 0;
630
631 if((blockpos.inode = pfsBlockGetLastSegmentDescriptorInode(clink, &result)))
632 {
633 blockpos.block_offset=blockpos.byte_offset=0;
634 blockpos.block_segment=clink->u.inode->number_data-1;
635 val-=pfsBlockExpandSegment(clink, &blockpos, val);
636 while (val && ((result=pfsBlockAllocNewSegment(clink, &blockpos, val))>=0)){
637 val-=result;
638 result=0;
639 }
640 pfsCacheFree(blockpos.inode);
641 }
642 return result;
643}
644
645void pfsFreeZones(pfs_cache_t *pfree)
646{
648 int result;
649 pfs_mount_t *pfsMount = pfree->pfsMount;
650 pfs_inode_t *inode = pfree->u.inode;
651 u32 nextsegdesc = 1, limit = inode->number_data, i, j = 0, zones;
652 pfs_blockinfo_t *bi;
653 pfs_cache_t *clink;
654
655 zones = (u32)(inode->size / pfsMount->zsize);
656 if(inode->size % pfsMount->zsize)
657 zones++;
658 if(inode->number_segdesg + zones == inode->number_blocks)
659 return;
660
661 j = zones;
662 b.number = 0;
663 clink = pfsCacheUsedAdd(pfree);
664
665 // iterate through each of the block segments used by the inode
666 for (i = 1; i < limit && j; i++)
667 {
668 if(pfsFixIndex(i) == 0)
669 {
670 if ((clink = pfsBlockGetNextSegment(clink, &result)) == 0)
671 return;
672
673 nextsegdesc++;
674 }
675 else
676 {
677 bi = &clink->u.inode->data[pfsFixIndex(i)];
678
679 if(j < bi->count)
680 {
681 bi->count -= j;
682 b.subpart = bi->subpart;
683 b.count = j;
684 b.number = bi->number +
685 bi->count;
686 j = 0;
687 clink->flags |= PFS_CACHE_FLAG_DIRTY;
688 }
689 else
690 j -= bi->count;
691 }
692 }
693
694 pfree->u.inode->number_data = i;
695 pfree->u.inode->number_blocks = zones + nextsegdesc;
696 pfree->u.inode->number_segdesg = nextsegdesc;
697 pfree->u.inode->last_segment.number = clink->u.inode->data[0].number;
698 pfree->u.inode->last_segment.subpart= clink->u.inode->data[0].subpart;
699 pfree->u.inode->last_segment.count = clink->u.inode->data[0].count;
700 pfree->flags |= PFS_CACHE_FLAG_DIRTY;
701
702 if (b.number)
703 pfsBitmapFreeBlockSegment(pfsMount, &b);
704
705 for( ; i < limit; i++)
706 {
707 if (pfsFixIndex(i) == 0)
708 {
709 if((clink = pfsBlockGetNextSegment(clink, &result)) == 0)
710 return;
711 }
712 bi = &clink->u.inode->data[pfsFixIndex(i)];
713 pfsBitmapFreeBlockSegment(pfsMount, bi);
714 pfsCacheMarkClean(pfsMount, bi->subpart, bi->number<<pfsMount->inode_scale,
715 (bi->number+bi->count)<<pfsMount->inode_scale);
716 }
717
718 pfsCacheFree(clink);
719}
#define ENOENT
Definition errno.h:23
#define ELOOP
Definition errno.h:193
#define ENAMETOOLONG
Definition errno.h:191
#define ENOTDIR
Definition errno.h:59
#define EACCES
Definition errno.h:45
#define EROFS
Definition errno.h:79
#define FIO_S_IFMT
Definition iox_stat.h:39
#define FIO_S_IFLNK
Definition iox_stat.h:41
#define FIO_S_IFDIR
Definition iox_stat.h:45
u32 count
start sector of fragmented bd/file