Start collecting transition tools for upgrading a system to 3.0.
Subject to be moved elsewhere in case we decided on a more cmplete upgrade toolset. Right now, put it here so that people can upgrade their wtmp files if they want. Note that the tool is not yet fully bullet-prrof. It tries to do its best however.
This commit is contained in:
parent
757495f1e4
commit
45802f2a8a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=20551
5
tools/3.0-upgrade/Makefile
Normal file
5
tools/3.0-upgrade/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
all: cvt-wtmp
|
||||
|
||||
cvt-wtmp: cvt-wtmp.c /usr/include/utmp.h
|
||||
|
||||
.include <bsd.prog.mk>
|
237
tools/3.0-upgrade/cvt-wtmp.c
Normal file
237
tools/3.0-upgrade/cvt-wtmp.c
Normal file
@ -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 <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sysexits.h>
|
||||
#include <unistd.h>
|
||||
#include <utmp.h>
|
||||
|
||||
|
||||
#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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user