|
Home - Old Man Programmer
| Displaying projects/sac/fixers//fixtmp.c
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/file.h>
#include <utmp.h>
#define WARP_FACTOR (60*60*24*120) /* 120 days */
/* Simple fixtmp does this:
* - Scan forward until it hits bad utmp.
* - Reposition at end of wtmp and scan backwards until it hits bad utmp.
* - Ouput the good stuff.
* |------> [bad entries] <------|
* This works OK with just one corrupted area, not so good with lots of corruption/
* libc5/glib wtmp sharing.
*/
/*
* usage: fixtmp <corrupted file> [ <output file> | - ]
*/
int main(int argc, char **argv)
{
struct utmp u;
int n, in, out;
time_t lastent;
long rpos, lpos, pos;
if (argc < 3) {
fprintf(stderr,"Usage: %s <infile> [ <outfile> | - ]\n",argv[0]);
exit(1);
}
if ((in = open(argv[1],O_RDONLY,0)) < 0) {
fprintf(stderr,"unable to open '%s' for reading.\n",argv[1]);
exit(1);
}
if (!strcmp("-",argv[2])) out = 1;
else {
if ((out = open(argv[2],O_WRONLY | O_CREAT, 0666)) < 0) {
fprintf(stderr,"unable to open '%s' for writing.\n",argv[2]);
exit(1);
}
}
lastent = 0;
rpos = 0;
while((n=read(in,&u,sizeof(struct utmp))) == sizeof(struct utmp)) {
if (u.ut_time == 0) continue;
if (lastent && (u.ut_time < (lastent-WARP_FACTOR) || u.ut_time > (lastent+WARP_FACTOR))) break;
lastent = u.ut_time;
if (write(out,&u,sizeof(struct utmp)) < 0) {
fprintf(stderr,"error writing output.\n");
exit(1);
}
rpos += sizeof(struct utmp);
}
if (n == 0) {
fprintf(stderr,"no corruption detected.\n");
exit(0);
}
if (n < 0) {
fprintf(stderr,"error reading input file.\n");
exit(1);
}
if (n < sizeof(struct utmp)) {
fprintf(stderr,"premature EOF, truncating.\n");
exit(0);
}
fprintf(stderr,"corruption detected, scanning from end.\n");
if ((pos = lseek(in,0,SEEK_END)) < 0) {
fprintf(stderr,"error seeking to EOF -- aborting.\n");
exit(1);
}
lpos = pos - sizeof(struct utmp);
lastent = 0;
while(lpos > 0) {
if ((pos = lseek(in,lpos,SEEK_SET)) < 0) {
fprintf(stderr,"error scanning backwards.\n");
exit(1);
}
if ((n = read(in,&u,sizeof(struct utmp))) != sizeof(struct utmp)) {
fprintf(stderr,"error reading input.\n");
exit(1);
}
if (lastent && (u.ut_time < (lastent-WARP_FACTOR) || u.ut_time > (lastent+WARP_FACTOR))) break;
lastent = u.ut_time;
lpos -= sizeof(struct utmp);
}
lpos += sizeof(struct utmp);
while((n=read(in,&u,sizeof(struct utmp))) == sizeof(struct utmp)) {
if (write(out,&u,sizeof(struct utmp)) < 0) {
fprintf(stderr,"error writing output.\n");
exit(1);
}
}
fprintf(stderr,"%ld bytes removed.\n",lpos-rpos);
exit(0);
}
|