2 * Copyright 2008-2017, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
7 #include "fssh_stdio.h"
11 #include "bfs_control.h"
18 command_checkfs(int argc
, const char* const* argv
)
20 if (argc
== 2 && !strcmp(argv
[1], "--help")) {
21 fssh_dprintf("Usage: %s [-c]\n"
22 " -c Check only; don't perform any changes\n", argv
[0]);
26 bool checkOnly
= false;
27 if (argc
== 2 && !strcmp(argv
[1], "-c"))
30 int rootDir
= _kern_open_dir(-1, "/myfs");
34 struct check_control result
;
35 memset(&result
, 0, sizeof(result
));
36 result
.magic
= BFS_IOCTL_CHECK_MAGIC
;
39 result
.flags
|= BFS_FIX_BITMAP_ERRORS
| BFS_REMOVE_WRONG_TYPES
40 | BFS_REMOVE_INVALID
| BFS_FIX_NAME_MISMATCHES
| BFS_FIX_BPLUSTREES
;
44 fssh_status_t status
= _kern_ioctl(rootDir
, BFS_IOCTL_START_CHECKING
,
45 &result
, sizeof(result
));
49 uint64 attributeDirectories
= 0, attributes
= 0;
50 uint64 files
= 0, directories
= 0, indices
= 0;
52 uint32 previousPass
= result
.pass
;
54 // check all files and report errors
55 while (_kern_ioctl(rootDir
, BFS_IOCTL_CHECK_NEXT_NODE
, &result
,
56 sizeof(result
)) == B_OK
) {
57 if (++counter
% 50 == 0) {
58 fssh_dprintf("%9" FSSH_B_PRIu64
" nodes processed\x1b[1A\n",
62 if (result
.pass
== BFS_CHECK_PASS_BITMAP
) {
64 fssh_dprintf("%s (inode = %" FSSH_B_PRIdINO
")", result
.name
,
66 if ((result
.errors
& BFS_MISSING_BLOCKS
) != 0)
67 fssh_dprintf(", some blocks weren't allocated");
68 if ((result
.errors
& BFS_BLOCKS_ALREADY_SET
) != 0)
69 fssh_dprintf(", has blocks already set");
70 if ((result
.errors
& BFS_INVALID_BLOCK_RUN
) != 0)
71 fssh_dprintf(", has invalid block run(s)");
72 if ((result
.errors
& BFS_COULD_NOT_OPEN
) != 0)
73 fssh_dprintf(", could not be opened");
74 if ((result
.errors
& BFS_WRONG_TYPE
) != 0)
75 fssh_dprintf(", has wrong type");
76 if ((result
.errors
& BFS_NAMES_DONT_MATCH
) != 0)
77 fssh_dprintf(", names don't match");
78 if ((result
.errors
& BFS_INVALID_BPLUSTREE
) != 0)
79 fssh_dprintf(", invalid b+tree");
83 if ((result
.mode
& (S_INDEX_DIR
| 0777)) == S_INDEX_DIR
)
85 else if (result
.mode
& S_ATTR_DIR
)
86 attributeDirectories
++;
87 else if (result
.mode
& S_ATTR
)
89 else if (S_ISDIR(result
.mode
))
93 } else if (result
.pass
== BFS_CHECK_PASS_INDEX
) {
94 if (previousPass
!= result
.pass
) {
95 fssh_dprintf("Recreating broken index b+trees...\n");
96 previousPass
= result
.pass
;
103 if (_kern_ioctl(rootDir
, BFS_IOCTL_STOP_CHECKING
, &result
, sizeof(result
))
105 _kern_close(rootDir
);
109 _kern_close(rootDir
);
111 fssh_dprintf(" %" FSSH_B_PRIu64
" nodes checked,\n\t%" FSSH_B_PRIu64
112 " blocks not allocated,\n\t%" FSSH_B_PRIu64
" blocks already set,\n\t%"
113 B_PRIu64
" blocks could be freed\n\n", counter
, result
.stats
.missing
,
114 result
.stats
.already_set
, result
.stats
.freed
);
115 fssh_dprintf("\tfiles\t\t%" FSSH_B_PRIu64
"\n\tdirectories\t%"
117 "\tattributes\t%" FSSH_B_PRIu64
"\n\tattr. dirs\t%" FSSH_B_PRIu64
"\n"
118 "\tindices\t\t%" FSSH_B_PRIu64
"\n", files
, directories
, attributes
,
119 attributeDirectories
, indices
);
121 fssh_dprintf("\n\tdirect block runs\t\t%" FSSH_B_PRIu64
" (%" FSSH_B_PRIu64
122 ")\n", result
.stats
.direct_block_runs
,
123 result
.stats
.blocks_in_direct
* result
.stats
.block_size
);
124 fssh_dprintf("\tindirect block runs\t\t%" FSSH_B_PRIu64
" (in %"
125 FSSH_B_PRIu64
" array blocks, %" FSSH_B_PRIu64
")\n",
126 result
.stats
.indirect_block_runs
, result
.stats
.indirect_array_blocks
,
127 result
.stats
.blocks_in_indirect
* result
.stats
.block_size
);
128 fssh_dprintf("\tdouble indirect block runs\t%" FSSH_B_PRIu64
" (in %"
129 FSSH_B_PRIu64
" array blocks, %" FSSH_B_PRIu64
")\n",
130 result
.stats
.double_indirect_block_runs
,
131 result
.stats
.double_indirect_array_blocks
,
132 result
.stats
.blocks_in_double_indirect
* result
.stats
.block_size
);
134 if (result
.status
== B_ENTRY_NOT_FOUND
)
135 result
.status
= B_OK
;
137 return result
.status
;
141 } // namespace FSShell