1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
|
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2024, Huawei Technologies Co, Ltd.
*
* Authors: Zhihao Cheng <chengzhihao1@huawei.com>
*/
#ifndef __FSCK_UBIFS_H__
#define __FSCK_UBIFS_H__
/* Exit codes used by fsck-type programs */
#define FSCK_OK 0 /* No errors */
#define FSCK_NONDESTRUCT 1 /* File system errors corrected */
#define FSCK_REBOOT 2 /* System should be rebooted */
#define FSCK_UNCORRECTED 4 /* File system errors left uncorrected */
#define FSCK_ERROR 8 /* Operational error */
#define FSCK_USAGE 16 /* Usage or syntax error */
#define FSCK_CANCELED 32 /* Aborted with a signal or ^C */
#define FSCK_LIBRARY 128 /* Shared library error */
/*
* There are 6 working modes for fsck:
* NORMAL_MODE: Check the filesystem, ask user whether or not to fix the
* problem as long as inconsistent data is found during checking.
* SAFE_MODE: Check and safely repair the filesystem, if there are any
* data dropping operations needed by fixing, fsck will fail.
* DANGER_MODE0:Check and repair the filesystem according to TNC, data dropping
* will be reported. If TNC/master/log is corrupted, fsck will fail.
* DANGER_MODE1:Check and forcedly repair the filesystem according to TNC,
* turns to @REBUILD_MODE mode automatically if TNC/master/log is
* corrupted.
* REBUILD_MODE:Scan entire UBI volume to find all nodes, and rebuild the
* filesystem, always make fsck success.
* CHECK_MODE: Make no changes to the filesystem, only check the filesystem.
*/
enum { NORMAL_MODE = 0, SAFE_MODE, DANGER_MODE0,
DANGER_MODE1, REBUILD_MODE, CHECK_MODE };
/* Types of inconsistent problems */
enum { SB_CORRUPTED = 0 };
/**
* scanned_node - common header node.
* @exist: whether the node is found by scanning
* @lnum: LEB number of the scanned node
* @offs: scanned node's offset within @lnum
* @len: length of scanned node
* @sqnum: sequence number
*/
struct scanned_node {
bool exist;
int lnum;
int offs;
int len;
unsigned long long sqnum;
};
/**
* scanned_ino_node - scanned inode node.
* @header: common header of scanned node
* @key: the key of inode node
* @is_xattr: %1 for xattr inode, otherwise %0
* @is_encrypted: %1 for encrypted inode, otherwise %0
* @mode: file mode
* @nlink: number of hard links
* @xcnt: count of extended attributes this inode has
* @xsz: summarized size of all extended attributes in bytes
* @xnms: sum of lengths of all extended attribute names
* @size: inode size in bytes
* @rb: link in the tree of valid inode nodes or deleted inode nodes
*/
struct scanned_ino_node {
struct scanned_node header;
union ubifs_key key;
unsigned int is_xattr:1;
unsigned int is_encrypted:1;
unsigned int mode;
unsigned int nlink;
unsigned int xcnt;
unsigned int xsz;
unsigned int xnms;
unsigned long long size;
struct rb_node rb;
};
/**
* scanned_dent_node - scanned dentry node.
* @header: common header of scanned node
* @key: the key of dentry node
* @can_be_found: whether this dentry can be found from '/'
* @type: file type, reg/dir/symlink/block/char/fifo/sock
* @nlen: name length
* @name: dentry name
* @inum: target inode number
* @rb: link in the trees of:
* 1) valid dentry nodes or deleted dentry node
* 2) all scanned dentry nodes from same file
* @list: link in the list dentries for looking up/deleting
*/
struct scanned_dent_node {
struct scanned_node header;
union ubifs_key key;
bool can_be_found;
unsigned int type;
unsigned int nlen;
char name[UBIFS_MAX_NLEN + 1];
ino_t inum;
struct rb_node rb;
struct list_head list;
};
/**
* scanned_data_node - scanned data node.
* @header: common header of scanned node
* @key: the key of data node
* @size: uncompressed data size in bytes
* @rb: link in the tree of all scanned data nodes from same file
* @list: link in the list for deleting
*/
struct scanned_data_node {
struct scanned_node header;
union ubifs_key key;
unsigned int size;
struct rb_node rb;
struct list_head list;
};
/**
* scanned_trun_node - scanned truncation node.
* @header: common header of scanned node
* @new_size: size after truncation
*/
struct scanned_trun_node {
struct scanned_node header;
unsigned long long new_size;
};
/**
* struct ubifs_fsck_info - UBIFS fsck information.
* @mode: working mode
* @failure_reason: reasons for failed operations
* @lpt_status: the status of lpt, could be: %0(OK), %FR_LPT_CORRUPTED or
* %FR_LPT_INCORRECT
*/
struct ubifs_fsck_info {
int mode;
unsigned int failure_reason;
unsigned int lpt_status;
};
#define FSCK(c) ((struct ubifs_fsck_info*)c->private)
static inline const char *mode_name(const struct ubifs_info *c)
{
if (!c->private)
return "";
switch (FSCK(c)->mode) {
case NORMAL_MODE:
return ",normal mode";
case SAFE_MODE:
return ",safe mode";
case DANGER_MODE0:
return ",danger mode";
case DANGER_MODE1:
return ",danger + rebuild mode";
case REBUILD_MODE:
return ",rebuild mode";
case CHECK_MODE:
return ",check mode";
default:
return "";
}
}
#define log_out(c, fmt, ...) \
printf("%s[%d] (%s%s): " fmt "\n", c->program_name ? : "noprog",\
getpid(), c->dev_name ? : "-", mode_name(c), \
##__VA_ARGS__)
#define log_err(c, err, fmt, ...) do { \
printf("%s[%d][ERROR] (%s%s): %s: " fmt, \
c->program_name ? : "noprog", getpid(), \
c->dev_name ? : "-", mode_name(c), \
__FUNCTION__, ##__VA_ARGS__); \
if (err) \
printf(" - %s", strerror(err)); \
printf("\n"); \
} while (0)
/* Exit code for fsck program. */
extern int exit_code;
/* problem.c */
bool fix_problem(const struct ubifs_info *c, int problem_type);
/* load_fs.c */
int ubifs_load_filesystem(struct ubifs_info *c);
void ubifs_destroy_filesystem(struct ubifs_info *c);
/* extract_files.c */
bool parse_ino_node(struct ubifs_info *c, int lnum, int offs, void *node,
union ubifs_key *key, struct scanned_ino_node *ino_node);
bool parse_dent_node(struct ubifs_info *c, int lnum, int offs, void *node,
union ubifs_key *key, struct scanned_dent_node *dent_node);
bool parse_data_node(struct ubifs_info *c, int lnum, int offs, void *node,
union ubifs_key *key, struct scanned_data_node *data_node);
bool parse_trun_node(struct ubifs_info *c, int lnum, int offs, void *node,
union ubifs_key *key, struct scanned_trun_node *trun_node);
#endif
|