23#include "bitmap_fsck.h"
26#include "fsck-ioctl.h"
29IRX_ID(
"fsck", PFS_MAJOR, PFS_MINOR);
39static int fsckWriteEnabled;
40static int fsckAutoMode;
41static int fsckVerbosityLevel;
42extern u32 pfsMetaSize;
43extern u32 pfsBlockSize;
46#define IO_BUFFER_SIZE 256
47#define IO_BUFFER_SIZE_BYTES (IO_BUFFER_SIZE * 512)
50static u8 IOBuffer[IO_BUFFER_SIZE_BYTES];
52#define FSCK_NUM_SUPPORTED_DEVICES 1
53#define FSCK_MAX_PATH_LEVELS 64
54#define FSCK_MAX_PATH_SEG_LENGTH 256
56static int fsckEventFlagID;
57static int fsckThreadID;
58static char fsckPathBuffer[FSCK_MAX_PATH_LEVELS][FSCK_MAX_PATH_SEG_LENGTH];
60static u32 ZoneSizes[0x41];
61static u32 ZoneMap[0x41];
64const char *fsckGetChar(
void)
66 static char buffer[80];
71 if (gets(buffer) != NULL)
73 if (fgets(buffer,
sizeof(buffer), stdin) != NULL)
76 for (pChar = buffer; *pChar !=
'\0'; pChar++) {
77 if (isgraph(*(
const unsigned char *)pChar)) {
89static int fsckPromptUserAction(
const char *description,
int mode)
95 if (fsckWriteEnabled != 0) {
96 if (fsckAutoMode != 0) {
106 unsigned char choice;
108 printf(
"%s (%s)? ", description, mode == 0 ?
"n/y" :
"y/n");
110 choice = *fsckGetChar();
111 }
while (choice !=
'n' && choice !=
'y');
131static int fsckPromptUserAction2(
const char *description,
int mode)
135 if (fsckWriteEnabled != 0) {
136 if (fsckAutoMode != 0) {
144 unsigned char choice;
146 printf(
"%s (%s)? ", description, mode == 0 ?
"n/y" :
"y/n");
148 choice = *fsckGetChar();
149 }
while (choice !=
'n' && choice !=
'y');
169static int DisplayUsageHelp(
void)
171 PFS_PRINTF(
"error: Usage: fsck [-n <num>]\n");
172 return MODULE_NO_RESIDENT_END;
176static int fsckCheckExtendedAttribute(
pfs_mount_t *mount)
178 int remaining, size, result;
180 iomanX_lseek(mount->fd, 0, SEEK_SET);
181 for (result = 0, remaining = 0x1FF8; remaining != 0; remaining -= size) {
182 size = (remaining > IO_BUFFER_SIZE) ? IO_BUFFER_SIZE : remaining;
184 if (iomanX_read(mount->fd, IOBuffer, size * 512) == -
EIO) {
185 PFS_PRINTF(
"cannot read extended attribute %d\n", -
EIO);
186 if (fsckPromptUserAction(
" nullify extended attribute", 1) == 0) {
190 memset(IOBuffer, 0, IO_BUFFER_SIZE_BYTES);
191 iomanX_lseek(mount->fd, 0, SEEK_SET);
192 for (remaining = 0x1FF8; remaining != 0; remaining -= size) {
193 size = (remaining > IO_BUFFER_SIZE) ? IO_BUFFER_SIZE : remaining;
195 if ((result = iomanX_write(mount->fd, IOBuffer, size * 512)) < 0) {
196 PFS_PRINTF(
"error: could not nullify extended attribute.\n");
209static int fsckCheckDirentryInode(
pfs_cache_t *clink);
217 if ((clink = pfsInodeGetData(mount, mount->root_dir.subpart, mount->root_dir.number, &result)) != NULL) {
218 if (fsckVerbosityLevel >= 2) {
221 if (fsckCheckDirentryInode(clink) == 0) {
222 pResultClink = clink;
235static void pfsPrintPWD(
void)
240 for (i = 0, pName = fsckPathBuffer[0]; (u32)i <
fsckRuntimeData.status.PWDLevel; i++, pName += FSCK_MAX_PATH_SEG_LENGTH) {
241 printf(
"/%s", pName);
250static int pfsInitDirEnt(
pfs_mount_t *mount, u16 subpart, u32 inodeNumber, u32 number,
int isDir)
256 if (fsckPromptUserAction(
" initialize directory entry", 1) != 0) {
257 if ((clink = pfsCacheGetData(mount, subpart, number, PFS_CACHE_FLAG_NOLOAD, &result)) != NULL) {
260 memset(clink->u.dentry, 0, pfsMetaSize);
261 pDentry = clink->u.dentry;
265 pDentry->inode = inodeNumber;
266 pDentry->sub = (u8)subpart;
269 pDentry->path[0] =
'.';
270 pDentry->path[1] =
'\0';
275 pDentry->inode = inodeNumber;
276 pDentry->sub = (u8)subpart;
279 pDentry->path[0] =
'.';
280 pDentry->path[1] =
'.';
281 pDentry->path[2] =
'\0';
286 pDentry = clink->u.dentry + 1;
289 clink->flags |= PFS_CACHE_FLAG_DIRTY;
302 u32 chunk, bit,
count;
305 pfsBitmapSetupInfo(mount, &bitmapinfo, blockinfo->subpart, blockinfo->number);
307 chunk = bitmapinfo.chunk;
310 if ((clink = pfsBitmapReadPartition(mount, blockinfo->subpart, chunk)) != NULL) {
311 for (pBitmap = &clink->u.bitmap[bitmapinfo.index]; (pBitmap < clink->u.bitmap + 0x100) &&
count != 0; pBitmap++, bitmapinfo.bit = 0) {
312 for (bit = bitmapinfo.bit; (bit < 32) && (
count != 0); bit++,
count--) {
313 if ((*pBitmap & (1 << bit)) == 0) {
314 PFS_PRINTF(
"not marked as used.\n");
315 if (fsckPromptUserAction(
" Mark in use", 1) != 0) {
316 *pBitmap |= (1 << bit);
317 clink->flags |= PFS_CACHE_FLAG_DIRTY;
325 bitmapinfo.index = 0;
336static int fsckCheckZones(u32 number, u32 size)
338 u32 index, zone, remaining, bit, startBit;
342 index = number >> 20;
343 zone = (number >> 5) & 0x7FFF;
344 startBit = number & 31;
345 for (remaining = size; remaining != 0;) {
346 pBitmap = pfsBitmapRead(index);
349 if (pBitmap != NULL) {
350 for (pZone = &pBitmap->bitmap[zone]; (pZone < pBitmap->bitmap + 0x8000) && remaining != 0; pZone++) {
351 for (bit = startBit; bit < 32 && remaining != 0; bit++, remaining--) {
352 if ((*pZone & (1 << bit)) != 0) {
353 PFS_PRINTF(
"error: overlapped zone found.\n");
357 *pZone |= (1 << bit);
358 pBitmap->isDirty = 1;
364 pfsBitmapFree(pBitmap);
375static void fsckFillInode(
pfs_cache_t *inodeClink,
pfs_cache_t *blockClink, u32 blocks, u32 entries, u32 segdesg)
378 if (blockClink == NULL) {
381 memset(&blockClink->u.inode->next_segment, 0,
sizeof(blockClink->u.inode->next_segment));
383 inodeClink->u.inode->number_segdesg = (blocks - segdesg) * inodeClink->pfsMount->zsize;
384 inodeClink->u.inode->subpart = 0;
385 if (!FIO_S_ISDIR(inodeClink->u.inode->mode)) {
386 inodeClink->u.inode->attr &= ~PFS_FIO_ATTR_CLOSED;
389 inodeClink->u.inode->number_blocks = blocks;
390 inodeClink->u.inode->number_data = entries;
391 inodeClink->u.inode->number_segdesg = segdesg;
392 inodeClink->u.inode->last_segment.subpart = blockClink->sub;
393 inodeClink->u.inode->last_segment.number = blockClink->block >> blockClink->pfsMount->inode_scale;
394 blockClink->flags |= PFS_CACHE_FLAG_DIRTY;
395 inodeClink->flags |= PFS_CACHE_FLAG_DIRTY;
399static int fsckCheckDirentryInode(
pfs_cache_t *direntInodeClink)
404 u32 index, new_index, blocks, segdesg, inodeStart, sector;
411 blockClink = pfsCacheUsedAdd(direntInodeClink);
414 for (index = 0; (index < direntInodeClink->u.inode->number_data) && (result == 0); index++)
416 new_index = pfsFixIndex(index);
418 if (index != 0 && new_index == 0) {
419 pInodeInfo = &blockClink->u.inode->next_segment;
420 pfsCacheFree(blockClink);
421 if ((blockClink = pfsCacheGetData(direntInodeClink->pfsMount, pInodeInfo->subpart, pInodeInfo->number << direntInodeClink->pfsMount->inode_scale, PFS_CACHE_FLAG_SEGI, &result)) == NULL) {
422 if ((result == -
EIO) && (fsckPromptUserAction(
" Remove rest of file", 1) != 0)) {
423 fsckFillInode(direntInodeClink, NULL, blocks, index, segdesg);
433 pInodeInfo = &blockClink->u.inode->data[new_index];
434 if ((direntInodeClink->pfsMount->num_subs < pInodeInfo->subpart) || (pInodeInfo->count == 0) || (pInodeInfo->number < 2) || (ZoneSizes[pInodeInfo->subpart] < ((pInodeInfo->number + pInodeInfo->count) << direntInodeClink->pfsMount->sector_scale))) {
437 printf(
" contains a bad zone.");
438 if (fsckPromptUserAction(
" Remove rest of file", 1) != 0) {
439 fsckFillInode(direntInodeClink, blockClink, blocks, index, segdesg);
448 if (new_index != 0) {
449 if (FIO_S_ISDIR(direntInodeClink->u.inode->mode)) {
451 for (i = 0; i < pInodeInfo->count; i++) {
452 inodeStart = (pInodeInfo->number + i) << direntInodeClink->pfsMount->inode_scale;
455 for (sector = 0; (sector < (u32)(1 << direntInodeClink->pfsMount->inode_scale)) && (inodeOffset < direntInodeClink->u.inode->size); sector++) {
456 inodeOffset += pfsMetaSize;
457 if ((childDirentBlockClink = pfsCacheGetData(direntInodeClink->pfsMount, pInodeInfo->subpart, inodeStart + sector, PFS_CACHE_FLAG_NOTHING, &result)) != NULL) {
458 pfsCacheFree(childDirentBlockClink);
464 PFS_PRINTF(
"could not read directory block.\n");
465 if ((result = pfsInitDirEnt(direntInodeClink->pfsMount, pInodeInfo->subpart, inodeStart + sector, direntInodeClink->u.inode->inode_block.number, (index == 1 && i == 0) ? sector < 1 : 0)) < 0) {
472 if (fsckVerbosityLevel >= 10) {
479 for (i = 0; i < pInodeInfo->count; i++) {
480 if (direntInodeClink->pfsMount->blockDev->transfer(direntInodeClink->pfsMount->fd, IOBuffer, pInodeInfo->subpart, (pInodeInfo->number + i) << direntInodeClink->pfsMount->sector_scale, 1 << direntInodeClink->pfsMount->sector_scale, PFS_IO_MODE_READ) == 0) {
481 if (fsckVerbosityLevel >= 10) {
489 PFS_PRINTF(
"could not read zone.\n");
490 if (fsckPromptUserAction(
" Remove rest of file", 1) != 0) {
491 fsckFillInode(direntInodeClink, blockClink, blocks, index, segdesg);
502 if ((result = fsckCheckFileBitmap(direntInodeClink->pfsMount, pInodeInfo)) >= 0) {
503 result = fsckCheckZones(pInodeInfo->number + ZoneMap[pInodeInfo->subpart], pInodeInfo->count);
505 if (fsckPromptUserAction(
" Remove rest of file", 1) != 0) {
506 fsckFillInode(direntInodeClink, blockClink, blocks, index, segdesg);
509 }
else if (result < 0)
518 blocks += pInodeInfo->count;
530 if (fsckVerbosityLevel >= 2)
533 pfsCacheFree(blockClink);
541 u32 dEntrySize, offset;
545 dEntrySize = (u32)((u8 *)dentry - (u8 *)clink->u.dentry);
547 if (clink->u.dentry > dentry)
550 dEntrySize = dEntrySize >> 9 << 9;
551 pDEntryNew = (
pfs_dentry_t *)((u8 *)clink->u.dentry + dEntrySize);
552 for (pDEntry = NULL, offset = 0; offset <
sizeof(
pfs_dentry_t); offset += aLen, pDEntry = pDEntryNew, pDEntryNew = (
pfs_dentry_t *)((u8 *)pDEntryNew + aLen)) {
553 aLen = pDEntryNew->aLen & 0x0FFF;
555 if (pDEntryNew == dentry) {
556 if (pDEntry != NULL) {
557 pDEntry->aLen = (pDEntry->aLen &
FIO_S_IFMT) | ((pDEntry->aLen & 0x0FFF) + aLen);
559 pDEntryNew->inode = 0;
560 pDEntryNew->pLen = 0;
563 clink->flags |= PFS_CACHE_FLAG_DIRTY;
572 if ((SelfInodeClink->sub != dentry->sub) || (SelfInodeClink->u.inode->inode_block.number != dentry->inode)) {
573 PFS_PRINTF(
"'.' point not itself.\n");
574 if (fsckPromptUserAction(
" Fix", 1) != 0) {
575 dentry->sub = SelfInodeClink->u.inode->inode_block.subpart;
576 dentry->inode = SelfInodeClink->u.inode->inode_block.number;
577 SelfDEntryClink->flags |= PFS_CACHE_FLAG_DIRTY;
585 if ((ParentInodeClink->sub != dentry->sub) || (ParentInodeClink->u.inode->inode_block.number != dentry->inode)) {
586 PFS_PRINTF(
"'..' point not parent.\n");
587 if (fsckPromptUserAction(
" Fix", 1) != 0) {
588 dentry->sub = ParentInodeClink->u.inode->inode_block.subpart;
589 dentry->inode = ParentInodeClink->u.inode->inode_block.number;
590 SelfDEntryClink->flags |= PFS_CACHE_FLAG_DIRTY;
601 memset(fsckPathBuffer[
fsckRuntimeData.status.PWDLevel], 0, FSCK_MAX_PATH_SEG_LENGTH);
602 strncpy(fsckPathBuffer[
fsckRuntimeData.status.PWDLevel], dentry->path, dentry->pLen);
605 if (fsckVerbosityLevel >= 2) {
607 if (FIO_S_ISDIR(dentry->aLen)) {
612 if (FIO_S_ISREG(dentry->aLen)) {
613 if (FileInodeDataClink->pfsMount->blockDev->transfer(FileInodeDataClink->pfsMount->fd, IOBuffer, FileInodeDataClink->sub, (FileInodeDataClink->block + 1) << pfsBlockSize, 1 << pfsBlockSize, PFS_IO_MODE_READ) != 0) {
614 PFS_PRINTF(
"could not read extended attribute.\n");
615 if (fsckPromptUserAction(
" initialize attribute", 1) != 0) {
616 memset(IOBuffer, 0, 1024);
618 if (FileInodeDataClink->pfsMount->blockDev->transfer(FileInodeDataClink->pfsMount->fd, IOBuffer, FileInodeDataClink->sub, (FileInodeDataClink->block + 1) << pfsBlockSize, 1 << pfsBlockSize, PFS_IO_MODE_WRITE) != 0) {
629 fsckCheckDirentryInode(FileInodeDataClink);
630 if (FIO_S_ISDIR(dentry->aLen)) {
632 fsckCheckFiles(FileInodeClink, FileInodeDataClink);
639 PFS_PRINTF(
"error: exceed max directory depth.\n");
650 u32 inodeOffset, dEntrySize;
654 BlockPosition.inode = pfsCacheUsedAdd(InodeClink);
655 BlockPosition.block_segment = 1;
656 BlockPosition.block_offset = 0;
657 BlockPosition.byte_offset = 0;
658 if ((DEntryClink = pfsGetDentriesChunk(&BlockPosition, &result)) == NULL) {
659 pfsCacheFree(BlockPosition.inode);
663 pDEntry = DEntryClink->u.dentry;
666 while (inodeOffset < InodeClink->u.inode->size) {
668 if (pDEntry >= (
pfs_dentry_t *)(DEntryClink->u.data + 1024)) {
671 pfsCacheFree(DEntryClink);
672 if (pfsInodeSync(&BlockPosition, 1024, InodeClink->u.inode->number_data) != 0 || (DEntryClink = pfsGetDentriesChunk(&BlockPosition, &result)) == NULL) {
677 pDEntry = DEntryClink->u.dentry;
681 for (pDEntryEnd = pDEntry + 1; pDEntry < pDEntryEnd; pDEntry = (
pfs_dentry_t *)((u8 *)pDEntry + dEntrySize), inodeOffset += dEntrySize) {
686 dEntrySize = pDEntry->aLen & 0x0FFF;
688 if (dEntrySize & 3) {
689 dEntrySize = (u32)((u8 *)pDEntryEnd - (u8 *)pDEntry);
690 PFS_PRINTF(
"directory entry is not aligned.\n");
692 if (fsckPromptUserAction(
" Fix", 1) != 0) {
693 pDEntry->aLen = (pDEntry->aLen & 0xF000) | dEntrySize;
694 DEntryClink->flags |= PFS_CACHE_FLAG_DIRTY;
698 if (dEntrySize < (u32)((pDEntry->pLen + 11) & ~3)) {
699 dEntrySize = (u32)((u8 *)pDEntryEnd - (u8 *)pDEntry);
700 PFS_PRINTF(
"directory entry is too small.\n");
702 if (fsckPromptUserAction(
" Fix", 1) != 0) {
703 if ((u32)((pDEntry->pLen + 11) & ~3) < dEntrySize) {
704 pDEntry->aLen = (pDEntry->aLen & 0xF000) | dEntrySize;
705 DEntryClink->flags |= PFS_CACHE_FLAG_DIRTY;
707 fsckFixDEntry(DEntryClink, pDEntry);
716 if (pDEntryEnd < (
pfs_dentry_t *)((u8 *)pDEntry + dEntrySize)) {
717 dEntrySize = (u32)((u8 *)pDEntryEnd - (u8 *)pDEntry);
718 PFS_PRINTF(
"directory entry is too long.\n");
719 if (fsckPromptUserAction(
" Fix", 1) != 0) {
720 fsckFixDEntry(DEntryClink, pDEntry);
727 if (pDEntry->inode != 0) {
728 if ((pDEntry->pLen == 1) && (pDEntry->path[0] ==
'.')) {
729 fsckCheckSelfEntry(InodeClink, DEntryClink, pDEntry);
730 }
else if ((pDEntry->pLen == 2) && (pDEntry->path[0] ==
'.')) {
731 fsckCheckParentEntry(ParentInodeClink, DEntryClink, pDEntry);
733 if ((FileInodeDataClink = pfsInodeGetData(InodeClink->pfsMount, pDEntry->sub, pDEntry->inode, &result)) != NULL) {
734 fsckCheckFile(InodeClink, FileInodeDataClink, pDEntry);
735 pfsCacheFree(FileInodeDataClink);
737 if (result == -
EIO) {
738 printf(
" contains an unreadable file '%.*s'.\n", pDEntry->pLen, pDEntry->path);
739 if (fsckPromptUserAction(
" Remove", 1) != 0)
740 fsckFixDEntry(DEntryClink, pDEntry);
754 pfsCacheFree(DEntryClink);
755 pfsCacheFree(BlockPosition.inode);
759static void fsckCompareBitmap(
pfs_mount_t *mount,
void *buffer)
762 u32 i, NumZones, zone;
763 u32 *pBitmap, ZoneStartOffset, *pRawBitmap, RawSize, unaligned, length, offset;
767 for (i = 0, offset = 0; i < mount->num_subs + 1; i++, offset++) {
768 RawSize = ZoneSizes[i] >> mount->sector_scale;
769 NumZones = RawSize / (mount->zsize << 3);
770 unaligned = RawSize % (mount->zsize << 3);
772 for (zone = 0; (unaligned == 0 && zone < NumZones) || (unaligned != 0 && zone < NumZones + 1); zone++) {
773 length = (zone == NumZones) ? unaligned : mount->zsize << 3;
776 pBitmap = pfsGetBitmapEntry(offset + (zone * (mount->zsize << 3)));
777 ZoneStartOffset = (i == 0) ? (0x2000 >> mount->sector_scale) + 1 : 1;
778 if (mount->blockDev->transfer(mount->fd, IOBuffer, i, (ZoneStartOffset + zone) << mount->sector_scale, 1 << mount->sector_scale, PFS_IO_MODE_READ) < 0) {
782 for (pRawBitmap = (u32 *)IOBuffer; pRawBitmap < (u32 *)(IOBuffer + (length >> 3)); pRawBitmap++, pBitmap++) {
784 if (*pRawBitmap != *pBitmap) {
785 PFS_PRINTF(
"bitmap unmatch %08lx, %08lx\n", *pRawBitmap, *pBitmap);
787 if (fsckPromptUserAction(
" Replace", 1) != 0)
789 if (fsckPromptUserAction2(
" Replace", 1) != 0)
792 *pRawBitmap = *pBitmap;
798 if (hasUpdate != 0) {
799 mount->blockDev->transfer(mount->fd, IOBuffer, i, (ZoneStartOffset + zone) << mount->sector_scale, 1 << mount->sector_scale, PFS_IO_MODE_WRITE);
806static void FsckThread(
void *arg)
813 if (fsckVerbosityLevel > 0) {
814 PFS_PRINTF(
"Check Root Directory...\n");
817 if (fsckVerbosityLevel > 0) {
818 PFS_PRINTF(
"Check Extended attribute...\n");
821 if (fsckCheckExtendedAttribute(mount) < 0) {
822 PFS_PRINTF(
"error: I cannot continue, giving up.\n");
823 goto fsck_thread_end;
826 if (fsckVerbosityLevel > 0) {
827 PFS_PRINTF(
"done.\n");
829 PFS_PRINTF(
"Check Root Directory...\n");
833 if ((clink = CheckRootDirectory(mount)) == NULL) {
834 PFS_PRINTF(
"error: I cannot continue, giving up.\n");
835 goto fsck_thread_end;
840 if (fsckVerbosityLevel > 0)
841 PFS_PRINTF(
"done.\n");
843 if (fsckVerbosityLevel > 0)
844 PFS_PRINTF(
"Check all files...\n");
846 fsckCheckFiles(clink, clink);
848 if (fsckVerbosityLevel > 0)
849 PFS_PRINTF(
"done.\n");
851 pfsCacheFlushAllDirty(mount);
857 if (fsckVerbosityLevel > 0) {
858 PFS_PRINTF(
"Compare bitmap...\n");
861 fsckCompareBitmap(mount, IOBuffer);
863 if (fsckVerbosityLevel > 0) {
864 PFS_PRINTF(
"done.\n");
871 if (mount->blockDev->transfer(mount->fd, super, 0, PFS_SUPER_SECTOR, 1, PFS_IO_MODE_READ) == 0) {
872 if (super->pfsFsckStat & PFS_FSCK_STAT_WRITE_ERROR) {
873 super->pfsFsckStat &= ~PFS_FSCK_STAT_WRITE_ERROR;
874 mount->blockDev->transfer(mount->fd, super, 0, PFS_SUPER_SECTOR, 1, PFS_IO_MODE_WRITE);
885 if (mount->blockDev->transfer(mount->fd, super, 0, PFS_SUPER_SECTOR, 1, PFS_IO_MODE_READ) == 0) {
886 super->pfsFsckStat |= PFS_FSCK_STAT_ERRORS_FIXED;
887 mount->blockDev->transfer(mount->fd, super, 0, PFS_SUPER_SECTOR, 1, PFS_IO_MODE_WRITE);
891 mount->blockDev->flushCache(mount->fd);
894 SetEventFlag(fsckEventFlagID, 1);
898static int fsckCheckBitmap(
pfs_mount_t *mount,
void *buffer)
900 u32 i,
count, block, BitmapStart, sector;
904 for (i = 0; i < mount->num_subs + 1; i++) {
906 for (block = 0,
count = pfsGetBitmapSizeBlocks(mount->sector_scale, ZoneSizes[i]); block <
count; block++) {
907 BitmapStart = block + 1;
909 BitmapStart += 0x2000 >> mount->sector_scale;
912 if ((result = mount->blockDev->transfer(mount->fd, buffer, i, BitmapStart << mount->sector_scale, 1 << mount->sector_scale, PFS_IO_MODE_READ)) < 0) {
913 PFS_PRINTF(
"cannot read bitmap\n");
914 if (fsckPromptUserAction(
" Overwrite", 1) == 0) {
918 for (sector = 0, result = 0; sector < (u32)(1 << mount->sector_scale); sector++) {
920 if (mount->blockDev->transfer(mount->fd, buffer, i, (BitmapStart << mount->sector_scale) + sector, 1, PFS_IO_MODE_READ) < 0) {
921 memset(buffer, -1, 512);
922 if ((result = mount->blockDev->transfer(mount->fd, buffer, i, (BitmapStart << mount->sector_scale) + sector, 1, PFS_IO_MODE_WRITE)) < 0) {
923 PFS_PRINTF(
"error: overwrite bitmap failed.\n");
936static int CheckSuperBlock(
pfs_mount_t *pMainPFSMount)
941 pMainPFSMount->num_subs = pMainPFSMount->blockDev->getSubNumber(pMainPFSMount->fd);
942 if (pMainPFSMount->blockDev->transfer(pMainPFSMount->fd, super, 0, PFS_SUPER_SECTOR, 1, PFS_IO_MODE_READ) < 0 || (super->magic != PFS_SUPER_MAGIC)) {
944 PFS_PRINTF(
"Read super block failed, try another.\n");
946 if (pMainPFSMount->blockDev->transfer(pMainPFSMount->fd, IOBuffer, 0, PFS_SUPER_BACKUP_SECTOR, 1, PFS_IO_MODE_READ) != 0) {
947 PFS_PRINTF(
"error: could not read any super block.\n");
951 result = (super->magic == PFS_SUPER_MAGIC) ? 0 : -
EIO;
954 PFS_PRINTF(
"error: could not read any super block.\n");
958 if (fsckPromptUserAction(
" Overwrite super block", 1) == 0) {
962 if ((result = pMainPFSMount->blockDev->transfer(pMainPFSMount->fd, IOBuffer, 0, PFS_SUPER_SECTOR, 1, PFS_IO_MODE_WRITE)) < 0) {
963 PFS_PRINTF(
"error: overwrite failed.\n");
969 if (super->version > PFS_FORMAT_VERSION) {
970 PFS_PRINTF(
"error: unknown version.\n");
974 if (((super->zone_size & (super->zone_size - 1)) != 0) ||
975 (super->zone_size < 0x800) ||
976 (0x20000 < super->zone_size)) {
977 PFS_PRINTF(
"error: invalid zone size.\n");
981 if (pMainPFSMount->num_subs < super->num_subs) {
982 PFS_PRINTF(
"filesystem larger than partition size.\n");
984 if (fsckPromptUserAction(
" Fix size", 1) == 0) {
988 super->num_subs = pMainPFSMount->num_subs;
989 if ((result = pMainPFSMount->blockDev->transfer(pMainPFSMount->fd, IOBuffer, 0, PFS_SUPER_SECTOR, 1, PFS_IO_MODE_WRITE)) < 0) {
990 PFS_PRINTF(
"error: could not fix the filesystem size.\n");
995 pMainPFSMount->zsize = super->zone_size;
996 pMainPFSMount->sector_scale = pfsGetScale(super->zone_size, 512);
997 pMainPFSMount->inode_scale = pfsGetScale(super->zone_size, 1024);
999 memcpy(&pMainPFSMount->root_dir, &super->root,
sizeof(pMainPFSMount->root_dir));
1000 memcpy(&pMainPFSMount->log, &super->log,
sizeof(pMainPFSMount->log));
1001 memcpy(&pMainPFSMount->current_dir, &super->root,
sizeof(pMainPFSMount->current_dir));
1002 pMainPFSMount->total_zones = 0;
1004 if (fsckVerbosityLevel) {
1005 PFS_PRINTF(
"\tlog check...\n");
1008 if ((result = pfsJournalRestore(pMainPFSMount)) < 0)
1011 memset(ZoneSizes, 0, 0x10);
1012 memset(ZoneMap, 0, 0x10);
1014 for (i = 0; (u32)i < pMainPFSMount->num_subs + 1; i++) {
1015 ZoneSizes[i] = pMainPFSMount->blockDev->getSize(pMainPFSMount->fd, i);
1017 ZoneMap[i] = (ZoneSizes[i - 1] >> pMainPFSMount->sector_scale) + ZoneMap[i - 1];
1021 if (fsckVerbosityLevel > 0) {
1022 PFS_PRINTF(
"\tCheck Bitmaps...\n");
1026 if ((result = fsckCheckBitmap(pMainPFSMount, IOBuffer)) >= 0) {
1029 if (fsckVerbosityLevel > 0) {
1030 PFS_PRINTF(
"\tdone.\n");
1033 for (i = 0, pFreeZones = pMainPFSMount->free_zone; (u32)i < pMainPFSMount->num_subs + 1; i++, pFreeZones++) {
1034 pMainPFSMount->total_zones += ZoneSizes[i] >> pMainPFSMount->sector_scale;
1035 pMainPFSMount->zfree += (*pFreeZones = pfsBitmapCalcFreeZones(pMainPFSMount, i));
1038 if (fsckVerbosityLevel > 0) {
1039 PFS_PRINTF(
"zonesz %ld, %ld zones, %ld free.\n", pMainPFSMount->zsize, pMainPFSMount->total_zones, pMainPFSMount->zfree);
1047static int FsckOpen(
iomanX_iop_file_t *fd,
const char *name,
int flags,
int mode)
1049 int blockfd, result;
1056 fsckWriteEnabled = mode & FSCK_MODE_WRITE;
1057 fsckAutoMode = mode & FSCK_MODE_AUTO;
1058 fsckVerbosityLevel = (mode & 0xF0) >> 4;
1060 if (MainPFSMount.fd) {
1064 if ((result = iomanX_getstat(name, &StatData)) < 0) {
1065 PFS_PRINTF(
"error: could not get status.\n");
1069 if (StatData.mode != APA_TYPE_PFS) {
1070 PFS_PRINTF(
"error: not PFS.\n");
1074 if ((pblockDevData = pfsGetBlockDeviceTable(name)) == NULL) {
1078 if ((blockfd = iomanX_open(name, O_RDWR)) < 0) {
1079 PFS_PRINTF(
"error: cannot open.\n");
1083 memset(&MainPFSMount, 0,
sizeof(MainPFSMount));
1084 MainPFSMount.fd = blockfd;
1085 MainPFSMount.blockDev = pblockDevData;
1087 if (fsckVerbosityLevel > 0) {
1088 PFS_PRINTF(
"Check Super Block...\n");
1091 if ((result = CheckSuperBlock(&MainPFSMount)) < 0) {
1092 MainPFSMount.fd = 0;
1093 PFS_PRINTF(
"error: cannot continue.\n");
1097 if (fsckVerbosityLevel > 0) {
1098 PFS_PRINTF(
"done.\n");
1101 if ((result = pfsBitmapPartInit(MainPFSMount.total_zones)) >= 0) {
1107 fsckRuntimeData.status.zoneUsed = MainPFSMount.total_zones - MainPFSMount.zfree;
1108 for (i = 0; (u32)i < MainPFSMount.num_subs + 1;
fsckRuntimeData.status.inodeBlockCount +=
count, i++) {
1109 count = pfsGetBitmapSizeBlocks(MainPFSMount.sector_scale, ZoneSizes[i]) + 1;
1111 count += (0x2000 >> MainPFSMount.sector_scale) + MainPFSMount.log.count;
1114 if (fsckCheckZones(ZoneMap[i],
count) < 0) {
1120 fd->privdata = &MainPFSMount;
1123 MainPFSMount.fd = 0;
1140static int fsckGetEstimatedTime(
pfs_mount_t *mount,
int *result)
1148 for (i = 0; i < 4; i++) {
1149 GetSystemTime(&SysClock1);
1150 mount->blockDev->transfer(mount->fd, IOBuffer, 0, 1 << mount->sector_scale, 1 << mount->sector_scale, PFS_IO_MODE_READ);
1151 GetSystemTime(&SysClock2);
1153 SysClockDiff.lo = SysClock2.lo - SysClock1.lo;
1154 SysClockDiff.hi = SysClock2.hi - SysClock1.hi - (SysClock2.lo < SysClock1.lo);
1155 SysClock2USec(&SysClockDiff, &sec, &usec);
1157 PFS_PRINTF(
"%ld system clocks = %ld.%06ld sec\n", SysClockDiff.lo, sec, usec);
1165 if ((*result = ((clock + 400) *
fsckRuntimeData.status.zoneUsed / 1000000)) == 0) {
1173static int FsckIoctl2(
iomanX_iop_file_t *fd,
int cmd,
void *arg,
unsigned int arglen,
void *buf,
unsigned int buflen)
1183 case FSCK_IOCTL2_CMD_GET_ESTIMATE:
1184 result = fsckGetEstimatedTime(fd->privdata, buf);
1186 case FSCK_IOCTL2_CMD_START:
1187 result = StartThread(fsckThreadID, fd->privdata);
1189 case FSCK_IOCTL2_CMD_WAIT:
1190 result = WaitEventFlag(fsckEventFlagID, 1, WEF_OR | WEF_CLEAR, &FlagBits);
1192 case FSCK_IOCTL2_CMD_POLL:
1193 result = PollEventFlag(fsckEventFlagID, 1, WEF_OR | WEF_CLEAR, &FlagBits);
1194 if (result == KE_EVF_COND) {
1198 case FSCK_IOCTL2_CMD_GET_STATUS:
1202 case FSCK_IOCTL2_CMD_STOP:
1213IOMANX_RETURN_VALUE_IMPL(0);
1216 IOMANX_RETURN_VALUE(0),
1217 IOMANX_RETURN_VALUE(0),
1218 IOMANX_RETURN_VALUE(0),
1221 IOMANX_RETURN_VALUE(0),
1222 IOMANX_RETURN_VALUE(0),
1223 IOMANX_RETURN_VALUE(0),
1224 IOMANX_RETURN_VALUE(0),
1225 IOMANX_RETURN_VALUE(0),
1226 IOMANX_RETURN_VALUE(0),
1227 IOMANX_RETURN_VALUE(0),
1228 IOMANX_RETURN_VALUE(0),
1229 IOMANX_RETURN_VALUE(0),
1230 IOMANX_RETURN_VALUE(0),
1231 IOMANX_RETURN_VALUE(0),
1232 IOMANX_RETURN_VALUE(0),
1233 IOMANX_RETURN_VALUE(0),
1234 IOMANX_RETURN_VALUE(0),
1235 IOMANX_RETURN_VALUE(0),
1236 IOMANX_RETURN_VALUE(0),
1237 IOMANX_RETURN_VALUE(0),
1238 IOMANX_RETURN_VALUE_S64(0),
1239 IOMANX_RETURN_VALUE(0),
1240 IOMANX_RETURN_VALUE(0),
1241 IOMANX_RETURN_VALUE(0),
1253int PFS_ENTRYPOINT(
int argc,
char **argv)
1258 for (argc--, argv++; argc > 0 && ((*argv)[0] ==
'-'); argc--, argv++) {
1259 if (!strcmp(
"-n", *argv)) {
1262 if (strtol(*argv, NULL, 10) < buffers) {
1263 buffers = strtol(*argv, NULL, 10);
1266 return DisplayUsageHelp();
1269 return DisplayUsageHelp();
1273 PFS_PRINTF(
"max depth %d, %d buffers.\n", FSCK_MAX_PATH_LEVELS - 1, buffers);
1275 if (pfsCacheInit(buffers, 1024) < 0) {
1276 PFS_PRINTF(
"error: cache initialization failed.\n");
1277 return MODULE_NO_RESIDENT_END;
1280 if (pfsBitmapInit() < 0) {
1281 PFS_PRINTF(
"error: bitmap initialization failed.\n");
1282 return MODULE_NO_RESIDENT_END;
1285 if ((fsckEventFlagID = fsckCreateEventFlag()) < 0) {
1286 return MODULE_NO_RESIDENT_END;
1289 if ((fsckThreadID = fsckCreateThread(&FsckThread, 0x2080)) < 0) {
1290 return MODULE_NO_RESIDENT_END;
1293 iomanX_DelDrv(FsckDevice.name);
1294 if (iomanX_AddDrv(&FsckDevice) == 0) {
1295 PFS_PRINTF(
"version %04x driver start.\n", IRX_VER(PFS_MAJOR, PFS_MINOR));
1296 return MODULE_RESIDENT_END;
1299 return MODULE_NO_RESIDENT_END;
u32 count
start sector of fragmented bd/file