]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/blob - logprint/logprint.c
c6e5051e8f8c4ece45e541e517b2903cc6fc84ed
[thirdparty/xfsprogs-dev.git] / logprint / logprint.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (c) 2000-2004 Silicon Graphics, Inc.
4 * All Rights Reserved.
5 */
6 #include <sys/types.h>
7 #include <sys/stat.h>
8
9 #include "libxfs.h"
10 #include "libxlog.h"
11
12 #include "logprint.h"
13
14 #define OP_PRINT 0
15 #define OP_PRINT_TRANS 1
16 #define OP_DUMP 2
17 #define OP_COPY 3
18
19 int print_data;
20 int print_only_data;
21 int print_inode;
22 int print_quota;
23 int print_buffer;
24 int print_overwrite;
25 int print_no_data;
26 int print_no_print;
27 static int print_operation = OP_PRINT;
28 static struct libxfs_init x;
29
30 static void
31 usage(void)
32 {
33 fprintf(stderr, _("Usage: %s [options...] <device>\n\n\
34 Options:\n\
35 -c try to continue if error found in log\n\
36 -C <filename> copy the log from the filesystem to filename\n\
37 -d dump the log in log-record format\n\
38 -e exit when an error is found in the log\n\
39 -f specified device is actually a file\n\
40 -l <device> filename of external log\n\
41 -n don't try and interpret log data\n\
42 -o print buffer data in hex\n\
43 -s <start blk> block # to start printing\n\
44 -v print \"overwrite\" data\n\
45 -t print out transactional view\n\
46 -b in transactional view, extract buffer info\n\
47 -i in transactional view, extract inode info\n\
48 -q in transactional view, extract quota info\n\
49 -D print only data; no decoding\n\
50 -V print version information\n"),
51 progname);
52 exit(1);
53 }
54
55 static int
56 logstat(
57 struct xfs_mount *mp,
58 struct xlog *log)
59 {
60 int fd;
61 char buf[BBSIZE];
62
63 /* On Linux we always read the superblock of the
64 * filesystem. We need this to get the length of the
65 * log. Otherwise we end up seeking forever. -- mkp
66 */
67 if ((fd = open(x.dname, O_RDONLY)) == -1) {
68 fprintf(stderr, _(" Can't open device %s: %s\n"),
69 x.dname, strerror(errno));
70 exit(1);
71 }
72 lseek(fd, 0, SEEK_SET);
73 if (read(fd, buf, sizeof(buf)) != sizeof(buf)) {
74 fprintf(stderr, _(" read of XFS superblock failed\n"));
75 exit(1);
76 }
77 close (fd);
78
79 if (!x.disfile) {
80 struct xfs_sb *sb = &mp->m_sb;
81
82 /*
83 * Conjure up a mount structure
84 */
85 libxfs_sb_from_disk(sb, (struct xfs_dsb *)buf);
86 mp->m_features |= libxfs_sb_version_to_features(&mp->m_sb);
87 mp->m_blkbb_log = sb->sb_blocklog - BBSHIFT;
88
89 xlog_init(mp, log);
90
91 if (!x.logname && sb->sb_logstart == 0) {
92 fprintf(stderr, _(" external log device not specified\n\n"));
93 usage();
94 /*NOTREACHED*/
95 }
96 } else {
97 struct stat s;
98
99 stat(x.dname, &s);
100
101 log->l_logBBsize = s.st_size >> 9;
102 log->l_logBBstart = 0;
103 log->l_sectBBsize = BTOBB(BBSIZE);
104 log->l_dev = mp->m_logdev_targp;
105 log->l_mp = mp;
106 }
107
108 if (x.logname && *x.logname) { /* External log */
109 if ((fd = open(x.logname, O_RDONLY)) == -1) {
110 fprintf(stderr, _("Can't open file %s: %s\n"),
111 x.logname, strerror(errno));
112 exit(1);
113 }
114 close(fd);
115 } else { /* Internal log */
116 x.logdev = x.ddev;
117 }
118
119 return 0;
120 }
121
122 int
123 main(int argc, char **argv)
124 {
125 int print_start = -1;
126 int c;
127 int logfd;
128 char *copy_file = NULL;
129 struct xlog log = {0};
130 xfs_mount_t mount;
131
132 setlocale(LC_ALL, "");
133 bindtextdomain(PACKAGE, LOCALEDIR);
134 textdomain(PACKAGE);
135 memset(&mount, 0, sizeof(mount));
136 print_exit = 1; /* -e is now default. specify -c to override */
137
138 progname = basename(argv[0]);
139 while ((c = getopt(argc, argv, "bC:cdefl:iqnors:tDVv")) != EOF) {
140 switch (c) {
141 case 'D':
142 print_only_data++;
143 print_data++;
144 break;
145 case 'b':
146 print_buffer++;
147 break;
148 case 'c':
149 /* default is to stop on error.
150 * -c turns this off.
151 */
152 print_exit = 0;
153 break;
154 case 'e':
155 /* -e is now default
156 */
157 print_exit = 1;
158 break;
159 case 'C':
160 print_operation = OP_COPY;
161 copy_file = optarg;
162 break;
163 case 'd':
164 print_operation = OP_DUMP;
165 break;
166 case 'f':
167 print_skip_uuid++;
168 x.disfile = 1;
169 break;
170 case 'l':
171 x.logname = optarg;
172 x.lisfile = 1;
173 break;
174 case 'i':
175 print_inode++;
176 break;
177 case 'q':
178 print_quota++;
179 break;
180 case 'n':
181 print_no_data++;
182 break;
183 case 'o':
184 print_data++;
185 break;
186 case 's':
187 print_start = atoi(optarg);
188 break;
189 case 't':
190 print_operation = OP_PRINT_TRANS;
191 break;
192 case 'v':
193 print_overwrite++;
194 break;
195 case 'V':
196 printf(_("%s version %s\n"), progname, VERSION);
197 exit(0);
198 default:
199 usage();
200 }
201 }
202
203 if (argc - optind != 1)
204 usage();
205
206 x.dname = argv[optind];
207
208 if (x.dname == NULL)
209 usage();
210
211 x.isreadonly = LIBXFS_ISINACTIVE;
212 printf(_("xfs_logprint:\n"));
213 if (!libxfs_init(&x))
214 exit(1);
215
216 libxfs_buftarg_init(&mount, x.ddev, x.logdev, x.rtdev);
217 logstat(&mount, &log);
218
219 logfd = (x.logfd < 0) ? x.dfd : x.logfd;
220
221 printf(_(" data device: 0x%llx\n"), (unsigned long long)x.ddev);
222
223 if (x.logname) {
224 printf(_(" log file: \"%s\" "), x.logname);
225 } else {
226 printf(_(" log device: 0x%llx "), (unsigned long long)x.logdev);
227 }
228
229 printf(_("daddr: %lld length: %lld\n\n"),
230 (long long)log.l_logBBstart, (long long)log.l_logBBsize);
231
232 ASSERT(log.l_logBBsize <= INT_MAX);
233
234 switch (print_operation) {
235 case OP_PRINT:
236 xfs_log_print(&log, logfd, print_start);
237 break;
238 case OP_PRINT_TRANS:
239 xfs_log_print_trans(&log, print_start);
240 break;
241 case OP_DUMP:
242 xfs_log_dump(&log, logfd, print_start);
243 break;
244 case OP_COPY:
245 xfs_log_copy(&log, logfd, copy_file);
246 break;
247 }
248 exit(0);
249 }