summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1999-08-31 18:12:44 +0000
committerphk <phk@FreeBSD.org>1999-08-31 18:12:44 +0000
commit34b4a59103c885a67ddfce77442f1e93c0d80f8f (patch)
treeff7884b0175b02feed72f86a659646e9da41cbfe /sbin
parentfec313fcbb2f45f7225dc79bfddc8820af309748 (diff)
downloadFreeBSD-src-34b4a59103c885a67ddfce77442f1e93c0d80f8f.zip
FreeBSD-src-34b4a59103c885a67ddfce77442f1e93c0d80f8f.tar.gz
Fix savecore so that it operates correctly on character devices with
sectorsizes up to 8k. Pointed out by: sos
Diffstat (limited to 'sbin')
-rw-r--r--sbin/savecore/savecore.c117
1 files changed, 90 insertions, 27 deletions
diff --git a/sbin/savecore/savecore.c b/sbin/savecore/savecore.c
index ad3213f..ffdd8a5 100644
--- a/sbin/savecore/savecore.c
+++ b/sbin/savecore/savecore.c
@@ -123,6 +123,8 @@ void check_kmem __P((void));
int check_space __P((void));
void clear_dump __P((void));
int Create __P((char *, int));
+void DumpRead __P((int fd, void *bp, int size, off_t off, int flag));
+void DumpWrite __P((int fd, void *bp, int size, off_t off, int flag));
int dump_exists __P((void));
char *find_dev __P((dev_t, int));
int get_crashtime __P((void));
@@ -285,31 +287,24 @@ void
check_kmem()
{
register char *cp;
- FILE *fp;
- char core_vers[1024];
-
- fp = fdopen(dumpfd, "r");
- if (fp == NULL) {
- syslog(LOG_ERR, "%s: fdopen: %m", ddname);
- exit(1);
- }
- fseek(fp, (off_t)(dumplo + ok(dump_nl[X_VERSION].n_value)), L_SET);
- fgets(core_vers, sizeof(core_vers), fp);
+ char core_vers[1024], *p;
+
+ DumpRead(dumpfd, core_vers, sizeof(core_vers),
+ (off_t)(dumplo + ok(dump_nl[X_VERSION].n_value)), L_SET);
+ core_vers[sizeof(core_vers) - 1] = '\0';
+ p = strchr(core_vers, '\n');
+ if (p)
+ p[1] = '\0';
if (strcmp(vers, core_vers) && kernel == 0)
syslog(LOG_WARNING,
- "warning: %s version mismatch:\n\t%s\nand\t%s\n",
+ "warning: %s version mismatch:\n\t\"%s\"\nand\t\"%s\"\n",
getbootfile(), vers, core_vers);
- (void)fseek(fp,
+ DumpRead(dumpfd, &panicstr, sizeof(panicstr),
(off_t)(dumplo + ok(dump_nl[X_PANICSTR].n_value)), L_SET);
- (void)fread(&panicstr, sizeof(panicstr), 1, fp);
if (panicstr) {
- (void)fseek(fp, dumplo + ok(panicstr), L_SET);
- cp = panic_mesg;
- do
- *cp = getc(fp);
- while (*cp++ && cp < &panic_mesg[sizeof(panic_mesg)]);
+ DumpRead(dumpfd, panic_mesg, sizeof(panic_mesg),
+ (off_t)(dumplo + ok(panicstr)), L_SET);
}
- /* Don't fclose(fp), we use dumpfd later. */
}
void
@@ -318,8 +313,8 @@ clear_dump()
long newdumplo;
newdumplo = 0;
- Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), L_SET);
- Write(dumpfd, &newdumplo, sizeof(newdumplo));
+ DumpWrite(dumpfd, &newdumplo, sizeof(newdumplo),
+ (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), L_SET);
}
int
@@ -327,8 +322,8 @@ dump_exists()
{
int newdumpmag;
- Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), L_SET);
- (void)Read(dumpfd, &newdumpmag, sizeof(newdumpmag));
+ DumpRead(dumpfd, &newdumpmag, sizeof(newdumpmag),
+ (off_t)(dumplo + ok(dump_nl[X_DUMPMAG].n_value)), L_SET);
if (newdumpmag != dumpmag) {
if (verbose)
syslog(LOG_WARNING, "magic number mismatch (%x != %x)",
@@ -528,8 +523,8 @@ get_crashtime()
{
time_t dumptime; /* Time the dump was taken. */
- Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_TIME].n_value)), L_SET);
- (void)Read(dumpfd, &dumptime, sizeof(dumptime));
+ DumpRead(dumpfd, &dumptime, sizeof(dumptime),
+ (off_t)(dumplo + ok(dump_nl[X_TIME].n_value)), L_SET);
if (dumptime == 0) {
if (verbose)
syslog(LOG_ERR, "dump time is zero");
@@ -548,8 +543,8 @@ void
get_dumpsize()
{
/* Read the dump size. */
- Lseek(dumpfd, (off_t)(dumplo + ok(dump_nl[X_DUMPSIZE].n_value)), L_SET);
- (void)Read(dumpfd, &dumpsize, sizeof(dumpsize));
+ DumpRead(dumpfd, &dumpsize, sizeof(dumpsize),
+ (off_t)(dumplo + ok(dump_nl[X_DUMPSIZE].n_value)), L_SET);
dumpsize *= getpagesize();
}
@@ -643,6 +638,74 @@ Lseek(fd, off, flag)
}
}
+/*
+ * DumpWrite and DumpRead block io requests to the * dump device.
+ */
+#define DUMPBUFSIZE 8192
+void
+DumpWrite(fd, bp, size, off, flag)
+ int fd, size, flag;
+ void *bp;
+ off_t off;
+{
+ unsigned char buf[DUMPBUFSIZE], *p, *q;
+ off_t pos;
+ int i, j;
+
+ if (flag != L_SET) {
+ syslog(LOG_ERR, "lseek: not LSET");
+ exit(2);
+ }
+ q = bp;
+ while (size) {
+ pos = off & ~(DUMPBUFSIZE - 1);
+ Lseek(fd, pos, flag);
+ (void)Read(fd, buf, sizeof(buf));
+ j = off & (DUMPBUFSIZE - 1);
+ p = buf + j;
+ i = size;
+ if (i > DUMPBUFSIZE - j)
+ i = DUMPBUFSIZE - j;
+ memcpy(p, q, i);
+ Lseek(fd, pos, flag);
+ (void)Write(fd, buf, sizeof(buf));
+ size -= i;
+ q += i;
+ off += i;
+ }
+}
+
+void
+DumpRead(fd, bp, size, off, flag)
+ int fd, size, flag;
+ void *bp;
+ off_t off;
+{
+ unsigned char buf[DUMPBUFSIZE], *p, *q;
+ off_t pos;
+ int i, j;
+
+ if (flag != L_SET) {
+ syslog(LOG_ERR, "lseek: not LSET");
+ exit(2);
+ }
+ q = bp;
+ while (size) {
+ pos = off & ~(DUMPBUFSIZE - 1);
+ Lseek(fd, pos, flag);
+ (void)Read(fd, buf, sizeof(buf));
+ j = off & (DUMPBUFSIZE - 1);
+ p = buf + j;
+ i = size;
+ if (i > DUMPBUFSIZE - j)
+ i = DUMPBUFSIZE - j;
+ memcpy(q, p, i);
+ size -= i;
+ q += i;
+ off += i;
+ }
+}
+
int
Create(file, mode)
char *file;
OpenPOWER on IntegriCloud