+ /*
+ * Get the current number and update the bounds file. Do the update
+ * now, because may fail later and don't want to overwrite anything.
+ */
+ (void)snprintf(path, sizeof(path), "%s/bounds", dirname);
+ if ((fp = fopen(path, "r")) == NULL)
+ goto err1;
+ if (fgets(buf, sizeof(buf), fp) == NULL) {
+ if (ferror(fp))
+err1: syslog(LOG_WARNING, "%s: %s", path, strerror(errno));
+ bounds = 0;
+ } else
+ bounds = atoi(buf);
+ if (fp != NULL)
+ (void)fclose(fp);
+ if ((fp = fopen(path, "w")) == NULL)
+ syslog(LOG_ERR, "%s: %m", path);
+ else {
+ (void)fprintf(fp, "%d\n", bounds + 1);
+ (void)fclose(fp);
+ }
+ (void)fclose(fp);
+
+ /* Create the core file. */
+ (void)snprintf(path, sizeof(path), "%s/vmcore.%d%s",
+ dirname, bounds, compress ? ".Z" : "");
+ if (compress) {
+ if ((fp = zopen(path, "w", 0)) == NULL) {
+ syslog(LOG_ERR, "%s: %s", path, strerror(errno));
+ exit(1);
+ }
+ } else
+ ofd = Create(path, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+
+ /* Open the raw device. */
+ rawp = rawname(ddname);
+ if ((ifd = open(rawp, O_RDONLY)) == -1) {
+ syslog(LOG_WARNING, "%s: %m; using block device", rawp);
+ ifd = dumpfd;
+ }
+
+ /* Read the dump size. */
+ Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_DUMPSIZE].n_value)), L_SET);
+ (void)Read(dumpfd, &dumpsize, sizeof(dumpsize));
+
+ /* Seek to the start of the core. */
+ Lseek(ifd, (off_t)dumplo, L_SET);
+
+ /* Copy the core file. */
+ dumpsize *= NBPG;
+ syslog(LOG_NOTICE, "writing %score to %s",
+ compress ? "compressed " : "", path);
+ for (; dumpsize > 0; dumpsize -= nr) {
+ (void)printf("%6dK\r", dumpsize / 1024);
+ (void)fflush(stdout);
+ nr = read(ifd, buf, MIN(dumpsize, sizeof(buf)));
+ if (nr <= 0) {
+ if (nr == 0)
+ syslog(LOG_WARNING,
+ "WARNING: EOF on dump device");
+ else
+ syslog(LOG_ERR, "%s: %m", rawp);
+ goto err2;
+ }
+ if (compress)
+ nw = fwrite(buf, 1, nr, fp);
+ else
+ nw = write(ofd, buf, nr);
+ if (nw != nr) {
+ syslog(LOG_ERR, "%s: %s",
+ path, strerror(nw == 0 ? EIO : errno));
+err2: syslog(LOG_WARNING,
+ "WARNING: vmcore may be incomplete");
+ (void)printf("\n");
+ exit(1);
+ }
+ }
+ (void)printf("\n");
+ (void)close(ifd);
+ if (compress)
+ (void)fclose(fp);
+ else
+ (void)close(ofd);
+
+ /* Copy the kernel. */
+ ifd = Open(vmunix ? vmunix : _PATH_UNIX, O_RDONLY);
+ (void)snprintf(path, sizeof(path), "%s/vmunix.%d%s",
+ dirname, bounds, compress ? ".Z" : "");
+ if (compress) {
+ if ((fp = zopen(path, "w", 0)) == NULL) {
+ syslog(LOG_ERR, "%s: %s", path, strerror(errno));
+ exit(1);
+ }
+ } else
+ ofd = Create(path, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ syslog(LOG_NOTICE, "writing %skernel to %s",
+ compress ? "compressed " : "", path);
+ while ((nr = read(ifd, buf, sizeof(buf))) > 0) {
+ if (compress)
+ nw = fwrite(buf, 1, nr, fp);
+ else
+ nw = write(ofd, buf, nr);
+ if (nw != nr) {
+ syslog(LOG_ERR, "%s: %s",
+ path, strerror(nw == 0 ? EIO : errno));
+ syslog(LOG_WARNING,
+ "WARNING: vmunix may be incomplete");
+ exit(1);
+ }
+ }
+ if (nr < 0) {
+ syslog(LOG_ERR, "%s: %s",
+ vmunix ? vmunix : _PATH_UNIX, strerror(errno));
+ syslog(LOG_WARNING,
+ "WARNING: vmunix may be incomplete");
+ exit(1);
+ }
+ if (compress)
+ (void)fclose(fp);
+ else
+ (void)close(ofd);