xref: /aosp_15_r20/external/e2fsprogs/debugfs/zap.c (revision 6a54128f25917bfc36a8a6e9d722c04a0b4641b6)
1*6a54128fSAndroid Build Coastguard Worker /*
2*6a54128fSAndroid Build Coastguard Worker  * zap.c --- zap block
3*6a54128fSAndroid Build Coastguard Worker  *
4*6a54128fSAndroid Build Coastguard Worker  * Copyright (C) 2012 Theodore Ts'o.  This file may be redistributed
5*6a54128fSAndroid Build Coastguard Worker  * under the terms of the GNU Public License.
6*6a54128fSAndroid Build Coastguard Worker  */
7*6a54128fSAndroid Build Coastguard Worker 
8*6a54128fSAndroid Build Coastguard Worker #include "config.h"
9*6a54128fSAndroid Build Coastguard Worker #include <stdio.h>
10*6a54128fSAndroid Build Coastguard Worker #include <unistd.h>
11*6a54128fSAndroid Build Coastguard Worker #include <stdlib.h>
12*6a54128fSAndroid Build Coastguard Worker #include <ctype.h>
13*6a54128fSAndroid Build Coastguard Worker #include <string.h>
14*6a54128fSAndroid Build Coastguard Worker #include <time.h>
15*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_ERRNO_H
16*6a54128fSAndroid Build Coastguard Worker #include <errno.h>
17*6a54128fSAndroid Build Coastguard Worker #endif
18*6a54128fSAndroid Build Coastguard Worker #include <sys/types.h>
19*6a54128fSAndroid Build Coastguard Worker #ifdef HAVE_GETOPT_H
20*6a54128fSAndroid Build Coastguard Worker #include <getopt.h>
21*6a54128fSAndroid Build Coastguard Worker #else
22*6a54128fSAndroid Build Coastguard Worker extern int optind;
23*6a54128fSAndroid Build Coastguard Worker extern char *optarg;
24*6a54128fSAndroid Build Coastguard Worker #endif
25*6a54128fSAndroid Build Coastguard Worker 
26*6a54128fSAndroid Build Coastguard Worker #include "debugfs.h"
27*6a54128fSAndroid Build Coastguard Worker 
do_zap_block(int argc,char * argv[],int sci_idx EXT2FS_ATTR ((unused)),void * infop EXT2FS_ATTR ((unused)))28*6a54128fSAndroid Build Coastguard Worker void do_zap_block(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)),
29*6a54128fSAndroid Build Coastguard Worker 		    void *infop EXT2FS_ATTR((unused)))
30*6a54128fSAndroid Build Coastguard Worker {
31*6a54128fSAndroid Build Coastguard Worker 	unsigned long	pattern = 0;
32*6a54128fSAndroid Build Coastguard Worker 	unsigned char	*buf;
33*6a54128fSAndroid Build Coastguard Worker 	ext2_ino_t	inode;
34*6a54128fSAndroid Build Coastguard Worker 	errcode_t	errcode;
35*6a54128fSAndroid Build Coastguard Worker 	blk64_t		block;
36*6a54128fSAndroid Build Coastguard Worker 	char		*file = NULL;
37*6a54128fSAndroid Build Coastguard Worker 	int		c, err;
38*6a54128fSAndroid Build Coastguard Worker 	int		offset = -1;
39*6a54128fSAndroid Build Coastguard Worker 	int		length = -1;
40*6a54128fSAndroid Build Coastguard Worker 	int		bit = -1;
41*6a54128fSAndroid Build Coastguard Worker 
42*6a54128fSAndroid Build Coastguard Worker 	if (check_fs_open(argv[0]))
43*6a54128fSAndroid Build Coastguard Worker 		return;
44*6a54128fSAndroid Build Coastguard Worker 	if (check_fs_read_write(argv[0]))
45*6a54128fSAndroid Build Coastguard Worker 		return;
46*6a54128fSAndroid Build Coastguard Worker 
47*6a54128fSAndroid Build Coastguard Worker 	reset_getopt();
48*6a54128fSAndroid Build Coastguard Worker 	while ((c = getopt (argc, argv, "b:f:l:o:p:")) != EOF) {
49*6a54128fSAndroid Build Coastguard Worker 		switch (c) {
50*6a54128fSAndroid Build Coastguard Worker 		case 'f':
51*6a54128fSAndroid Build Coastguard Worker 			file = optarg;
52*6a54128fSAndroid Build Coastguard Worker 			break;
53*6a54128fSAndroid Build Coastguard Worker 		case 'b':
54*6a54128fSAndroid Build Coastguard Worker 			bit = parse_ulong(optarg, argv[0],
55*6a54128fSAndroid Build Coastguard Worker 					  "bit", &err);
56*6a54128fSAndroid Build Coastguard Worker 			if (err)
57*6a54128fSAndroid Build Coastguard Worker 				return;
58*6a54128fSAndroid Build Coastguard Worker 			if (bit >= (int) current_fs->blocksize * 8) {
59*6a54128fSAndroid Build Coastguard Worker 				com_err(argv[0], 0, "The bit to flip "
60*6a54128fSAndroid Build Coastguard Worker 					"must be within a %d block\n",
61*6a54128fSAndroid Build Coastguard Worker 					current_fs->blocksize);
62*6a54128fSAndroid Build Coastguard Worker 				return;
63*6a54128fSAndroid Build Coastguard Worker 			}
64*6a54128fSAndroid Build Coastguard Worker 			break;
65*6a54128fSAndroid Build Coastguard Worker 		case 'p':
66*6a54128fSAndroid Build Coastguard Worker 			pattern = parse_ulong(optarg, argv[0],
67*6a54128fSAndroid Build Coastguard Worker 					      "pattern", &err);
68*6a54128fSAndroid Build Coastguard Worker 			if (err)
69*6a54128fSAndroid Build Coastguard Worker 				return;
70*6a54128fSAndroid Build Coastguard Worker 			if (pattern >= 256) {
71*6a54128fSAndroid Build Coastguard Worker 				com_err(argv[0], 0, "The fill pattern must "
72*6a54128fSAndroid Build Coastguard Worker 					"be an 8-bit value\n");
73*6a54128fSAndroid Build Coastguard Worker 				return;
74*6a54128fSAndroid Build Coastguard Worker 			}
75*6a54128fSAndroid Build Coastguard Worker 			break;
76*6a54128fSAndroid Build Coastguard Worker 		case 'o':
77*6a54128fSAndroid Build Coastguard Worker 			offset = parse_ulong(optarg, argv[0],
78*6a54128fSAndroid Build Coastguard Worker 					     "offset", &err);
79*6a54128fSAndroid Build Coastguard Worker 			if (err)
80*6a54128fSAndroid Build Coastguard Worker 				return;
81*6a54128fSAndroid Build Coastguard Worker 			if (offset >= (int) current_fs->blocksize) {
82*6a54128fSAndroid Build Coastguard Worker 				com_err(argv[0], 0, "The offset must be "
83*6a54128fSAndroid Build Coastguard Worker 					"within a %d block\n",
84*6a54128fSAndroid Build Coastguard Worker 					current_fs->blocksize);
85*6a54128fSAndroid Build Coastguard Worker 				return;
86*6a54128fSAndroid Build Coastguard Worker 			}
87*6a54128fSAndroid Build Coastguard Worker 			break;
88*6a54128fSAndroid Build Coastguard Worker 
89*6a54128fSAndroid Build Coastguard Worker 			break;
90*6a54128fSAndroid Build Coastguard Worker 		case 'l':
91*6a54128fSAndroid Build Coastguard Worker 			length = parse_ulong(optarg, argv[0],
92*6a54128fSAndroid Build Coastguard Worker 					     "length", &err);
93*6a54128fSAndroid Build Coastguard Worker 			if (err)
94*6a54128fSAndroid Build Coastguard Worker 				return;
95*6a54128fSAndroid Build Coastguard Worker 			break;
96*6a54128fSAndroid Build Coastguard Worker 		default:
97*6a54128fSAndroid Build Coastguard Worker 			goto print_usage;
98*6a54128fSAndroid Build Coastguard Worker 		}
99*6a54128fSAndroid Build Coastguard Worker 	}
100*6a54128fSAndroid Build Coastguard Worker 
101*6a54128fSAndroid Build Coastguard Worker 	if (bit > 0 && offset > 0) {
102*6a54128fSAndroid Build Coastguard Worker 		com_err(argv[0], 0, "The -o and -b options can not be mixed.");
103*6a54128fSAndroid Build Coastguard Worker 		return;
104*6a54128fSAndroid Build Coastguard Worker 	}
105*6a54128fSAndroid Build Coastguard Worker 
106*6a54128fSAndroid Build Coastguard Worker 	if (offset < 0)
107*6a54128fSAndroid Build Coastguard Worker 		offset = 0;
108*6a54128fSAndroid Build Coastguard Worker 	if (length < 0)
109*6a54128fSAndroid Build Coastguard Worker 		length = current_fs->blocksize - offset;
110*6a54128fSAndroid Build Coastguard Worker 	if ((offset + length) > (int) current_fs->blocksize) {
111*6a54128fSAndroid Build Coastguard Worker 		com_err(argv[0], 0, "The specified length is too bug\n");
112*6a54128fSAndroid Build Coastguard Worker 		return;
113*6a54128fSAndroid Build Coastguard Worker 	}
114*6a54128fSAndroid Build Coastguard Worker 
115*6a54128fSAndroid Build Coastguard Worker 	if (argc != optind+1) {
116*6a54128fSAndroid Build Coastguard Worker 	print_usage:
117*6a54128fSAndroid Build Coastguard Worker 		com_err(0, 0, "Usage:\tzap_block [-f file] [-o offset] "
118*6a54128fSAndroid Build Coastguard Worker 			"[-l length] [-p pattern] block_num");
119*6a54128fSAndroid Build Coastguard Worker 		com_err(0, 0, "\tzap_block [-f file] [-b bit] "
120*6a54128fSAndroid Build Coastguard Worker 			"block_num");
121*6a54128fSAndroid Build Coastguard Worker 		return;
122*6a54128fSAndroid Build Coastguard Worker 	}
123*6a54128fSAndroid Build Coastguard Worker 
124*6a54128fSAndroid Build Coastguard Worker 	block = parse_ulonglong(argv[optind], argv[0], "block", &err);
125*6a54128fSAndroid Build Coastguard Worker 	if (err)
126*6a54128fSAndroid Build Coastguard Worker 		return;
127*6a54128fSAndroid Build Coastguard Worker 
128*6a54128fSAndroid Build Coastguard Worker 	if (file) {
129*6a54128fSAndroid Build Coastguard Worker 		inode = string_to_inode(file);
130*6a54128fSAndroid Build Coastguard Worker 		if (!inode)
131*6a54128fSAndroid Build Coastguard Worker 			return;
132*6a54128fSAndroid Build Coastguard Worker 		errcode = ext2fs_bmap2(current_fs, inode, 0, 0, 0,
133*6a54128fSAndroid Build Coastguard Worker 				       block, 0, &block);
134*6a54128fSAndroid Build Coastguard Worker 		if (errcode) {
135*6a54128fSAndroid Build Coastguard Worker 			com_err(argv[0], errcode,
136*6a54128fSAndroid Build Coastguard Worker 				"while mapping logical block %llu\n",
137*6a54128fSAndroid Build Coastguard Worker 				(unsigned long long) block);
138*6a54128fSAndroid Build Coastguard Worker 			return;
139*6a54128fSAndroid Build Coastguard Worker 		}
140*6a54128fSAndroid Build Coastguard Worker 	}
141*6a54128fSAndroid Build Coastguard Worker 
142*6a54128fSAndroid Build Coastguard Worker 	buf = malloc(current_fs->blocksize);
143*6a54128fSAndroid Build Coastguard Worker 	if (!buf) {
144*6a54128fSAndroid Build Coastguard Worker 		com_err(argv[0], 0, "Couldn't allocate block buffer");
145*6a54128fSAndroid Build Coastguard Worker 		return;
146*6a54128fSAndroid Build Coastguard Worker 	}
147*6a54128fSAndroid Build Coastguard Worker 
148*6a54128fSAndroid Build Coastguard Worker 	errcode = io_channel_read_blk64(current_fs->io, block, 1, buf);
149*6a54128fSAndroid Build Coastguard Worker 	if (errcode) {
150*6a54128fSAndroid Build Coastguard Worker 		com_err(argv[0], errcode,
151*6a54128fSAndroid Build Coastguard Worker 			"while reading block %llu\n",
152*6a54128fSAndroid Build Coastguard Worker 			(unsigned long long) block);
153*6a54128fSAndroid Build Coastguard Worker 		goto errout;
154*6a54128fSAndroid Build Coastguard Worker 	}
155*6a54128fSAndroid Build Coastguard Worker 
156*6a54128fSAndroid Build Coastguard Worker 	if (bit >= 0)
157*6a54128fSAndroid Build Coastguard Worker 		buf[bit >> 3] ^= 1 << (bit & 7);
158*6a54128fSAndroid Build Coastguard Worker 	else
159*6a54128fSAndroid Build Coastguard Worker 		memset(buf+offset, pattern, length);
160*6a54128fSAndroid Build Coastguard Worker 
161*6a54128fSAndroid Build Coastguard Worker 	errcode = io_channel_write_blk64(current_fs->io, block, 1, buf);
162*6a54128fSAndroid Build Coastguard Worker 	if (errcode) {
163*6a54128fSAndroid Build Coastguard Worker 		com_err(argv[0], errcode,
164*6a54128fSAndroid Build Coastguard Worker 			"while write block %llu\n",
165*6a54128fSAndroid Build Coastguard Worker 			(unsigned long long) block);
166*6a54128fSAndroid Build Coastguard Worker 		goto errout;
167*6a54128fSAndroid Build Coastguard Worker 	}
168*6a54128fSAndroid Build Coastguard Worker 
169*6a54128fSAndroid Build Coastguard Worker errout:
170*6a54128fSAndroid Build Coastguard Worker 	free(buf);
171*6a54128fSAndroid Build Coastguard Worker 	return;
172*6a54128fSAndroid Build Coastguard Worker }
173*6a54128fSAndroid Build Coastguard Worker 
do_block_dump(int argc,char * argv[],int sci_idx EXT2FS_ATTR ((unused)),void * infop EXT2FS_ATTR ((unused)))174*6a54128fSAndroid Build Coastguard Worker void do_block_dump(int argc, char *argv[], int sci_idx EXT2FS_ATTR((unused)),
175*6a54128fSAndroid Build Coastguard Worker 		    void *infop EXT2FS_ATTR((unused)))
176*6a54128fSAndroid Build Coastguard Worker {
177*6a54128fSAndroid Build Coastguard Worker 	unsigned char	*buf;
178*6a54128fSAndroid Build Coastguard Worker 	ext2_ino_t	inode;
179*6a54128fSAndroid Build Coastguard Worker 	errcode_t	errcode;
180*6a54128fSAndroid Build Coastguard Worker 	blk64_t		block;
181*6a54128fSAndroid Build Coastguard Worker 	char		*file = NULL;
182*6a54128fSAndroid Build Coastguard Worker 	int		xattr_dump = 0;
183*6a54128fSAndroid Build Coastguard Worker 	int		c, err;
184*6a54128fSAndroid Build Coastguard Worker 
185*6a54128fSAndroid Build Coastguard Worker 	if (check_fs_open(argv[0]))
186*6a54128fSAndroid Build Coastguard Worker 		return;
187*6a54128fSAndroid Build Coastguard Worker 
188*6a54128fSAndroid Build Coastguard Worker 	reset_getopt();
189*6a54128fSAndroid Build Coastguard Worker 	while ((c = getopt (argc, argv, "f:x")) != EOF) {
190*6a54128fSAndroid Build Coastguard Worker 		switch (c) {
191*6a54128fSAndroid Build Coastguard Worker 		case 'f':
192*6a54128fSAndroid Build Coastguard Worker 			file = optarg;
193*6a54128fSAndroid Build Coastguard Worker 			break;
194*6a54128fSAndroid Build Coastguard Worker 		case 'x':
195*6a54128fSAndroid Build Coastguard Worker 			xattr_dump = 1;
196*6a54128fSAndroid Build Coastguard Worker 			break;
197*6a54128fSAndroid Build Coastguard Worker 		default:
198*6a54128fSAndroid Build Coastguard Worker 			goto print_usage;
199*6a54128fSAndroid Build Coastguard Worker 		}
200*6a54128fSAndroid Build Coastguard Worker 	}
201*6a54128fSAndroid Build Coastguard Worker 
202*6a54128fSAndroid Build Coastguard Worker 	if (argc != optind + 1) {
203*6a54128fSAndroid Build Coastguard Worker 	print_usage:
204*6a54128fSAndroid Build Coastguard Worker 		com_err(0, 0, "Usage: block_dump [-x] [-f inode] block_num");
205*6a54128fSAndroid Build Coastguard Worker 		return;
206*6a54128fSAndroid Build Coastguard Worker 	}
207*6a54128fSAndroid Build Coastguard Worker 
208*6a54128fSAndroid Build Coastguard Worker 	block = parse_ulonglong(argv[optind], argv[0], "block", &err);
209*6a54128fSAndroid Build Coastguard Worker 	if (err)
210*6a54128fSAndroid Build Coastguard Worker 		return;
211*6a54128fSAndroid Build Coastguard Worker 
212*6a54128fSAndroid Build Coastguard Worker 	if (file) {
213*6a54128fSAndroid Build Coastguard Worker 		inode = string_to_inode(file);
214*6a54128fSAndroid Build Coastguard Worker 		if (!inode)
215*6a54128fSAndroid Build Coastguard Worker 			return;
216*6a54128fSAndroid Build Coastguard Worker 		errcode = ext2fs_bmap2(current_fs, inode, 0, 0, 0,
217*6a54128fSAndroid Build Coastguard Worker 				       block, 0, &block);
218*6a54128fSAndroid Build Coastguard Worker 		if (errcode) {
219*6a54128fSAndroid Build Coastguard Worker 			com_err(argv[0], errcode,
220*6a54128fSAndroid Build Coastguard Worker 				"while mapping logical block %llu\n",
221*6a54128fSAndroid Build Coastguard Worker 				(unsigned long long) block);
222*6a54128fSAndroid Build Coastguard Worker 			return;
223*6a54128fSAndroid Build Coastguard Worker 		}
224*6a54128fSAndroid Build Coastguard Worker 	}
225*6a54128fSAndroid Build Coastguard Worker 
226*6a54128fSAndroid Build Coastguard Worker 	buf = malloc(current_fs->blocksize);
227*6a54128fSAndroid Build Coastguard Worker 	if (!buf) {
228*6a54128fSAndroid Build Coastguard Worker 		com_err(argv[0], 0, "Couldn't allocate block buffer");
229*6a54128fSAndroid Build Coastguard Worker 		return;
230*6a54128fSAndroid Build Coastguard Worker 	}
231*6a54128fSAndroid Build Coastguard Worker 
232*6a54128fSAndroid Build Coastguard Worker 	errcode = io_channel_read_blk64(current_fs->io, block, 1, buf);
233*6a54128fSAndroid Build Coastguard Worker 	if (errcode) {
234*6a54128fSAndroid Build Coastguard Worker 		com_err(argv[0], errcode,
235*6a54128fSAndroid Build Coastguard Worker 			"while reading block %llu\n",
236*6a54128fSAndroid Build Coastguard Worker 			(unsigned long long) block);
237*6a54128fSAndroid Build Coastguard Worker 		goto errout;
238*6a54128fSAndroid Build Coastguard Worker 	}
239*6a54128fSAndroid Build Coastguard Worker 
240*6a54128fSAndroid Build Coastguard Worker 	if (xattr_dump)
241*6a54128fSAndroid Build Coastguard Worker 		block_xattr_dump(stdout, buf, current_fs->blocksize);
242*6a54128fSAndroid Build Coastguard Worker 	else
243*6a54128fSAndroid Build Coastguard Worker 		do_byte_hexdump(stdout, buf, current_fs->blocksize);
244*6a54128fSAndroid Build Coastguard Worker errout:
245*6a54128fSAndroid Build Coastguard Worker 	free(buf);
246*6a54128fSAndroid Build Coastguard Worker }
247