55 #include <sys/fm/util.h>
56 #include <fm/libfmevent.h>
57 #include <sys/int_fmtio.h>
58
59
60 /* fread/fwrite buffer size */
61 #define FBUFSIZE (1ULL << 20)
62
63 /* minimum size for output buffering */
64 #define MINCOREBLKSIZE (1ULL << 17)
65
66 /* create this file if metrics collection is enabled in the kernel */
67 #define METRICSFILE "METRICS.csv"
68
69 static char progname[9] = "savecore";
70 static char *savedir; /* savecore directory */
71 static char *dumpfile; /* source of raw crash dump */
72 static long bounds = -1; /* numeric suffix */
73 static long pagesize; /* dump pagesize */
74 static int dumpfd = -1; /* dumpfile descriptor */
75 static dumphdr_t corehdr, dumphdr; /* initial and terminal dumphdrs */
76 static boolean_t dump_incomplete; /* dumphdr indicates incomplete */
77 static boolean_t fm_panic; /* dump is the result of fm_panic */
78 static offset_t endoff; /* offset of end-of-dump header */
79 static int verbose; /* chatty mode */
80 static int disregard_valid_flag; /* disregard valid flag */
81 static int livedump; /* dump the current running system */
82 static int interactive; /* user invoked; no syslog */
83 static int csave; /* save dump compressed */
84 static int filemode; /* processing file, not dump device */
85 static int percent_done; /* progress indicator */
86 static int sec_done; /* progress last report time */
87 static hrtime_t startts; /* timestamp at start */
88 static volatile uint64_t saved; /* count of pages written */
89 static volatile uint64_t zpages; /* count of zero pages not written */
90 static dumpdatahdr_t datahdr; /* compression info */
91 static long coreblksize; /* preferred write size (st_blksize) */
92 static int cflag; /* run as savecore -c */
93 static int mflag; /* run as savecore -m */
94
222 code = 0;
223 break;
224
225 case SC_EXIT_PEND:
226 /*
227 * Raise an ireport saying why we are exiting. Do not
228 * raise if run as savecore -m. If something in the
229 * raise_event codepath calls logprint avoid recursion.
230 */
231 if (!mflag && logprint_raised++ == 0)
232 raise_event(SC_EVENT_SAVECORE_FAILURE, buf);
233 code = 2;
234 break;
235
236 case SC_EXIT_FM:
237 code = 3;
238 break;
239
240 case SC_EXIT_ERR:
241 default:
242 if (!mflag && logprint_raised++ == 0)
243 raise_event(SC_EVENT_SAVECORE_FAILURE, buf);
244 code = 1;
245 break;
246 }
247
248 exit(code);
249 }
250
251 /*
252 * System call / libc wrappers that exit on error.
253 */
254 static int
255 Open(const char *name, int oflags, mode_t mode)
256 {
257 int fd;
258
259 if ((fd = open64(name, oflags, mode)) == -1)
260 logprint(SC_SL_ERR | SC_EXIT_ERR, "open(\"%s\"): %s",
261 name, strerror(errno));
262 return (fd);
282 Fseek(offset_t off, FILE *f)
283 {
284 if (fseeko64(f, off, SEEK_SET) != 0)
285 logprint(SC_SL_ERR | SC_EXIT_ERR, "fseeko64: %s",
286 strerror(errno));
287 }
288
289 typedef struct stat64 Stat_t;
290
291 static void
292 Fstat(int fd, Stat_t *sb, const char *fname)
293 {
294 if (fstat64(fd, sb) != 0)
295 logprint(SC_SL_ERR | SC_EXIT_ERR, "fstat(\"%s\"): %s", fname,
296 strerror(errno));
297 }
298
299 static void
300 Stat(const char *fname, Stat_t *sb)
301 {
302 if (stat64(fname, sb) != 0)
303 logprint(SC_SL_ERR | SC_EXIT_ERR, "stat(\"%s\"): %s", fname,
304 strerror(errno));
305 }
306
307 static void
308 Pread(int fd, void *buf, size_t size, offset_t off)
309 {
310 ssize_t sz = pread64(fd, buf, size, off);
311
312 if (sz < 0)
313 logprint(SC_SL_ERR | SC_EXIT_ERR,
314 "pread: %s", strerror(errno));
315 else if (sz != size)
316 logprint(SC_SL_ERR | SC_EXIT_ERR,
317 "pread: size %ld != %ld", sz, size);
318 }
319
320 static void
321 Pwrite(int fd, void *buf, size_t size, off64_t off)
322 {
323 if (pwrite64(fd, buf, size, off) != size)
324 logprint(SC_SL_ERR | SC_EXIT_ERR, "pwrite: %s",
1694 /*
1695 * If doing something other than extracting an existing dump (i.e.
1696 * dumpfile has been provided as an option), the user must be root.
1697 */
1698 if (geteuid() != 0 && dumpfile == NULL) {
1699 (void) fprintf(stderr, "%s: %s %s\n", progname,
1700 gettext("you must be root to use"), progname);
1701 exit(1);
1702 }
1703
1704 interactive = isatty(STDOUT_FILENO);
1705
1706 if (cflag && livedump)
1707 usage();
1708
1709 if (dumpfile == NULL || livedump)
1710 dumpfd = Open("/dev/dump", O_RDONLY, 0444);
1711
1712 if (dumpfile == NULL) {
1713 dumpfile = Zalloc(MAXPATHLEN);
1714 if (ioctl(dumpfd, DIOCGETDEV, dumpfile) == -1)
1715 logprint(SC_SL_NONE | SC_IF_ISATTY | SC_EXIT_ERR,
1716 "no dump device configured");
1717 }
1718
1719 if (mflag)
1720 return (message_save());
1721
1722 if (optind == argc - 1)
1723 savedir = argv[optind];
1724
1725 if (savedir == NULL || optind < argc - 1)
1726 usage();
1727
1728 if (livedump && ioctl(dumpfd, DIOCDUMP, NULL) == -1)
1729 logprint(SC_SL_NONE | SC_EXIT_ERR,
1730 "dedicated dump device required");
1731
1732 (void) close(dumpfd);
1733 dumpfd = -1;
1734
1735 Stat(dumpfile, &st);
1736
|
55 #include <sys/fm/util.h>
56 #include <fm/libfmevent.h>
57 #include <sys/int_fmtio.h>
58
59
60 /* fread/fwrite buffer size */
61 #define FBUFSIZE (1ULL << 20)
62
63 /* minimum size for output buffering */
64 #define MINCOREBLKSIZE (1ULL << 17)
65
66 /* create this file if metrics collection is enabled in the kernel */
67 #define METRICSFILE "METRICS.csv"
68
69 static char progname[9] = "savecore";
70 static char *savedir; /* savecore directory */
71 static char *dumpfile; /* source of raw crash dump */
72 static long bounds = -1; /* numeric suffix */
73 static long pagesize; /* dump pagesize */
74 static int dumpfd = -1; /* dumpfile descriptor */
75 static boolean_t have_dumpfile = B_TRUE; /* dumpfile existence */
76 static dumphdr_t corehdr, dumphdr; /* initial and terminal dumphdrs */
77 static boolean_t dump_incomplete; /* dumphdr indicates incomplete */
78 static boolean_t fm_panic; /* dump is the result of fm_panic */
79 static offset_t endoff; /* offset of end-of-dump header */
80 static int verbose; /* chatty mode */
81 static int disregard_valid_flag; /* disregard valid flag */
82 static int livedump; /* dump the current running system */
83 static int interactive; /* user invoked; no syslog */
84 static int csave; /* save dump compressed */
85 static int filemode; /* processing file, not dump device */
86 static int percent_done; /* progress indicator */
87 static int sec_done; /* progress last report time */
88 static hrtime_t startts; /* timestamp at start */
89 static volatile uint64_t saved; /* count of pages written */
90 static volatile uint64_t zpages; /* count of zero pages not written */
91 static dumpdatahdr_t datahdr; /* compression info */
92 static long coreblksize; /* preferred write size (st_blksize) */
93 static int cflag; /* run as savecore -c */
94 static int mflag; /* run as savecore -m */
95
223 code = 0;
224 break;
225
226 case SC_EXIT_PEND:
227 /*
228 * Raise an ireport saying why we are exiting. Do not
229 * raise if run as savecore -m. If something in the
230 * raise_event codepath calls logprint avoid recursion.
231 */
232 if (!mflag && logprint_raised++ == 0)
233 raise_event(SC_EVENT_SAVECORE_FAILURE, buf);
234 code = 2;
235 break;
236
237 case SC_EXIT_FM:
238 code = 3;
239 break;
240
241 case SC_EXIT_ERR:
242 default:
243 if (!mflag && logprint_raised++ == 0 && have_dumpfile)
244 raise_event(SC_EVENT_SAVECORE_FAILURE, buf);
245 code = 1;
246 break;
247 }
248
249 exit(code);
250 }
251
252 /*
253 * System call / libc wrappers that exit on error.
254 */
255 static int
256 Open(const char *name, int oflags, mode_t mode)
257 {
258 int fd;
259
260 if ((fd = open64(name, oflags, mode)) == -1)
261 logprint(SC_SL_ERR | SC_EXIT_ERR, "open(\"%s\"): %s",
262 name, strerror(errno));
263 return (fd);
283 Fseek(offset_t off, FILE *f)
284 {
285 if (fseeko64(f, off, SEEK_SET) != 0)
286 logprint(SC_SL_ERR | SC_EXIT_ERR, "fseeko64: %s",
287 strerror(errno));
288 }
289
290 typedef struct stat64 Stat_t;
291
292 static void
293 Fstat(int fd, Stat_t *sb, const char *fname)
294 {
295 if (fstat64(fd, sb) != 0)
296 logprint(SC_SL_ERR | SC_EXIT_ERR, "fstat(\"%s\"): %s", fname,
297 strerror(errno));
298 }
299
300 static void
301 Stat(const char *fname, Stat_t *sb)
302 {
303 if (stat64(fname, sb) != 0) {
304 have_dumpfile = B_FALSE;
305 logprint(SC_SL_ERR | SC_EXIT_ERR, "failed to get status "
306 "of file %s", fname);
307 }
308 }
309
310 static void
311 Pread(int fd, void *buf, size_t size, offset_t off)
312 {
313 ssize_t sz = pread64(fd, buf, size, off);
314
315 if (sz < 0)
316 logprint(SC_SL_ERR | SC_EXIT_ERR,
317 "pread: %s", strerror(errno));
318 else if (sz != size)
319 logprint(SC_SL_ERR | SC_EXIT_ERR,
320 "pread: size %ld != %ld", sz, size);
321 }
322
323 static void
324 Pwrite(int fd, void *buf, size_t size, off64_t off)
325 {
326 if (pwrite64(fd, buf, size, off) != size)
327 logprint(SC_SL_ERR | SC_EXIT_ERR, "pwrite: %s",
1697 /*
1698 * If doing something other than extracting an existing dump (i.e.
1699 * dumpfile has been provided as an option), the user must be root.
1700 */
1701 if (geteuid() != 0 && dumpfile == NULL) {
1702 (void) fprintf(stderr, "%s: %s %s\n", progname,
1703 gettext("you must be root to use"), progname);
1704 exit(1);
1705 }
1706
1707 interactive = isatty(STDOUT_FILENO);
1708
1709 if (cflag && livedump)
1710 usage();
1711
1712 if (dumpfile == NULL || livedump)
1713 dumpfd = Open("/dev/dump", O_RDONLY, 0444);
1714
1715 if (dumpfile == NULL) {
1716 dumpfile = Zalloc(MAXPATHLEN);
1717 if (ioctl(dumpfd, DIOCGETDEV, dumpfile) == -1) {
1718 have_dumpfile = B_FALSE;
1719 logprint(SC_SL_NONE | SC_IF_ISATTY | SC_EXIT_ERR,
1720 "no dump device configured");
1721 }
1722 }
1723
1724 if (mflag)
1725 return (message_save());
1726
1727 if (optind == argc - 1)
1728 savedir = argv[optind];
1729
1730 if (savedir == NULL || optind < argc - 1)
1731 usage();
1732
1733 if (livedump && ioctl(dumpfd, DIOCDUMP, NULL) == -1)
1734 logprint(SC_SL_NONE | SC_EXIT_ERR,
1735 "dedicated dump device required");
1736
1737 (void) close(dumpfd);
1738 dumpfd = -1;
1739
1740 Stat(dumpfile, &st);
1741
|