diff --git a/tools/3.0-upgrade/Makefile b/tools/3.0-upgrade/Makefile new file mode 100644 index 000000000000..68ab9f1f5dde --- /dev/null +++ b/tools/3.0-upgrade/Makefile @@ -0,0 +1,5 @@ +all: cvt-wtmp + +cvt-wtmp: cvt-wtmp.c /usr/include/utmp.h + +.include diff --git a/tools/3.0-upgrade/cvt-wtmp.c b/tools/3.0-upgrade/cvt-wtmp.c new file mode 100644 index 000000000000..9d034b1fc876 --- /dev/null +++ b/tools/3.0-upgrade/cvt-wtmp.c @@ -0,0 +1,237 @@ +/* + * Copyright (c) 1996 Joerg Wunsch + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id$ + * + */ + +/* + * Heuristics to convert old wtmp format to new one. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define OUT_NAMESIZE 8 +#define OUT_LINESIZE 8 +#define OUT_HOSTSIZE 16 + +struct olastlog { + time_t ll_time; + char ll_line[OUT_LINESIZE]; + char ll_host[OUT_HOSTSIZE]; +}; + +struct outmp { + char ut_line[OUT_LINESIZE]; + char ut_name[OUT_NAMESIZE]; + char ut_host[OUT_HOSTSIZE]; + long ut_time; +}; + +void usage(void); +void convert(const char *, int); + +/* + * NB: We cannot convert lastlog yet, but we don't need either. + */ + +void +usage(void) +{ + errx(EX_USAGE, "usage: cvt-wtmp [-n] /var/log/wtmp*"); +} + + +int +main(int argc, char **argv) +{ + int errs, i, nflag, rv; + + errs = nflag = 0; + while ((i = getopt(argc, argv, "n")) != EOF) + switch (i) + { + case 'n': + nflag++; + break; + + default: + errs++; + } + argc -= optind; + argv += optind; + + if (argc <= 0 || errs) + usage(); + + for (;argc > 0; argc--, argv++) + convert(*argv, nflag); + + return 0; +} + +void +convert(const char *name, int nflag) +{ + struct stat sb; + struct timeval tv[2]; + char xname[1024], yname[1024]; + unsigned char buf[128]; /* large enough to hold one wtmp record */ + int fd1, fd2; + size_t off; + int old, new; + time_t now, early, *t; + struct tm tm; + struct utmp u; + struct outmp *ou; + + if (stat(name, &sb) == -1) + { + warn("Cannot stat file \"%s\", continuing.", name); + return; + } + + now = time(NULL); + /* some point in time very early, before 386BSD 0.0 */ + tm.tm_sec = 0; tm.tm_min = 0; tm.tm_hour = 0; + tm.tm_mday = 1; tm.tm_mon = 2; tm.tm_year = 92; + tm.tm_isdst = 0; + early = mktime(&tm); + + tv[0].tv_sec = sb.st_atimespec.tv_sec; + tv[0].tv_usec = sb.st_atimespec.tv_nsec / 1000; + tv[1].tv_sec = sb.st_mtimespec.tv_sec; + tv[1].tv_usec = sb.st_mtimespec.tv_nsec / 1000; + + /* unzipping is handled best externally */ + if (strlen(name) > 3 && memcmp(&name[strlen(name) - 3], ".gz", 3) == 0) + { + warnx("Cannot handle gzipped files, ignoring \"%s\".", name); + return; + } + + (void) snprintf(xname, sizeof xname, "%s.new", name); + if (!nflag && (fd1 = open(xname, O_WRONLY|O_CREAT|O_TRUNC, 0644)) == -1) + err(EX_CANTCREAT, "Can't create new wtmp file"); + + if ((fd2 = open(name, O_RDONLY, 0)) == -1) + err(EX_UNAVAILABLE, "input file magically disappeared, i'm confused"); + + old = new = 0; off = 0; + memset(buf, 0, sizeof buf); + + while (read(fd2, &buf[off], sizeof(time_t)) == sizeof(time_t)) + { + t = (time_t *)&buf[off]; + off += sizeof(time_t); + if (off < sizeof(struct outmp)) + /* go on */ + continue; + if (*t < early || *t > now) + { + /* unreasonable, collect another entry */ + if (off > sizeof buf) + { + (void) unlink(xname); + errx(EX_UNAVAILABLE, "I can't seem to make sense out of file \"%s\"", + name); + } + continue; + } + /* time is reasonable, we seem to have collected a full entry */ + if (off == sizeof(struct utmp)) + { + /* new wtmp record */ + new++; + if (!nflag) + { + if (write(fd1, buf, sizeof(struct utmp)) != sizeof(struct utmp)) + err(EX_IOERR, "writing file \"%s\"", xname); + } + } + else if (off == sizeof(struct outmp)) + { + /* old fart */ + old++; + if (!nflag) + { + ou = (struct outmp *)buf; + memset(&u, 0, sizeof u); + memcpy(&u.ut_line, ou->ut_line, OUT_LINESIZE); + memcpy(&u.ut_name, ou->ut_name, OUT_NAMESIZE); + memcpy(&u.ut_host, ou->ut_host, OUT_HOSTSIZE); + memcpy(&u.ut_time, &ou->ut_time, sizeof u.ut_time); + if (write(fd1, &u, sizeof(struct utmp)) != sizeof(struct utmp)) + err(EX_IOERR, "writing file \"%s\"", xname); + } + } + else + { + warnx("Illegal record in file \"%s\", ignoring.", name); + off = 0; + continue; + } + off = 0; + /* + * Since the wtmp file is in chronologically acsending order, we + * can move the `early' time as we go. Allow for one hour + * time-of-day adjustments. + */ + early = *t - 3600; + memset(buf, 0, sizeof buf); + } + close(fd2); + + printf("File \"%s\": %d old and %d new records found.\n", + name, old, new); + + if (nflag) + return; + + (void) close(fd1); + (void) snprintf(yname, sizeof yname, "%s.bak", name); + + if (rename(name, yname) == -1) + err(EX_OSERR, "Cannot rename \"%s\" to \"%s\"", name, yname); + + if (rename(xname, name) == -1) + err(EX_OSERR, "Cannot rename \"%s\" to \"%s\"", xname, name); + + if (utimes(name, tv) == -1) + warn("Cannot adjust access and modification times for \"%s\"", name); +} +