1 /*- 2 * Copyright (c) 1980 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)itime.c 5.7 (Berkeley) 03/07/91"; 10 #endif /* not lint */ 11 12 #include <sys/param.h> 13 #include <ufs/dir.h> 14 #include <ufs/dinode.h> 15 #include <fcntl.h> 16 #include <protocols/dumprestore.h> 17 #include <errno.h> 18 #include <stdio.h> 19 #ifdef __STDC__ 20 #include <time.h> 21 #include <unistd.h> 22 #include <stdlib.h> 23 #include <string.h> 24 #endif 25 #include "dump.h" 26 27 struct dumpdates **ddatev = 0; 28 int nddates = 0; 29 int ddates_in = 0; 30 struct dumptime *dthead = 0; 31 32 void readdumptimes(); 33 int getrecord(); 34 int makedumpdate(); 35 36 static void dumprecout(); 37 38 void 39 initdumptimes() 40 { 41 FILE *df; 42 43 if ((df = fopen(dumpdates, "r")) == NULL) { 44 if (errno == ENOENT) { 45 msg("WARNING: no file `%s'\n", dumpdates); 46 return; 47 } 48 quit("cannot read %s: %s\n", dumpdates, strerror(errno)); 49 /* NOTREACHED */ 50 } 51 (void) flock(fileno(df), LOCK_SH); 52 readdumptimes(df); 53 fclose(df); 54 } 55 56 void 57 readdumptimes(df) 58 FILE *df; 59 { 60 register int i; 61 register struct dumptime *dtwalk; 62 63 for (;;) { 64 dtwalk = (struct dumptime *)calloc(1, sizeof (struct dumptime)); 65 if (getrecord(df, &(dtwalk->dt_value)) < 0) 66 break; 67 nddates++; 68 dtwalk->dt_next = dthead; 69 dthead = dtwalk; 70 } 71 72 ddates_in = 1; 73 /* 74 * arrayify the list, leaving enough room for the additional 75 * record that we may have to add to the ddate structure 76 */ 77 ddatev = (struct dumpdates **) 78 calloc(nddates + 1, sizeof (struct dumpdates *)); 79 dtwalk = dthead; 80 for (i = nddates - 1; i >= 0; i--, dtwalk = dtwalk->dt_next) 81 ddatev[i] = &dtwalk->dt_value; 82 } 83 84 void 85 getdumptime() 86 { 87 register struct dumpdates *ddp; 88 register int i; 89 char *fname; 90 91 fname = disk; 92 #ifdef FDEBUG 93 msg("Looking for name %s in dumpdates = %s for level = %c\n", 94 fname, dumpdates, level); 95 #endif 96 spcl.c_ddate = 0; 97 lastlevel = '0'; 98 99 initdumptimes(); 100 /* 101 * Go find the entry with the same name for a lower increment 102 * and older date 103 */ 104 ITITERATE(i, ddp) { 105 if (strncmp(fname, ddp->dd_name, sizeof (ddp->dd_name)) != 0) 106 continue; 107 if (ddp->dd_level >= level) 108 continue; 109 if (ddp->dd_ddate <= spcl.c_ddate) 110 continue; 111 spcl.c_ddate = ddp->dd_ddate; 112 lastlevel = ddp->dd_level; 113 } 114 } 115 116 void 117 putdumptime() 118 { 119 FILE *df; 120 register struct dumpdates *dtwalk; 121 register int i; 122 int fd; 123 char *fname; 124 125 if(uflag == 0) 126 return; 127 if ((df = fopen(dumpdates, "r+")) == NULL) 128 quit("cannot rewrite %s: %s\n", dumpdates, strerror(errno)); 129 fd = fileno(df); 130 (void) flock(fd, LOCK_EX); 131 fname = disk; 132 free(ddatev); 133 ddatev = 0; 134 nddates = 0; 135 dthead = 0; 136 ddates_in = 0; 137 readdumptimes(df); 138 if (fseek(df, 0L, 0) < 0) 139 quit("fseek: %s\n", strerror(errno)); 140 spcl.c_ddate = 0; 141 ITITERATE(i, dtwalk) { 142 if (strncmp(fname, dtwalk->dd_name, 143 sizeof (dtwalk->dd_name)) != 0) 144 continue; 145 if (dtwalk->dd_level != level) 146 continue; 147 goto found; 148 } 149 /* 150 * construct the new upper bound; 151 * Enough room has been allocated. 152 */ 153 dtwalk = ddatev[nddates] = 154 (struct dumpdates *)calloc(1, sizeof(struct dumpdates)); 155 nddates += 1; 156 found: 157 (void) strncpy(dtwalk->dd_name, fname, sizeof (dtwalk->dd_name)); 158 dtwalk->dd_level = level; 159 dtwalk->dd_ddate = spcl.c_date; 160 161 ITITERATE(i, dtwalk) { 162 dumprecout(df, dtwalk); 163 } 164 if (fflush(df)) 165 quit("%s: %s\n", dumpdates, strerror(errno)); 166 if (ftruncate(fd, ftell(df))) 167 quit("ftruncate (%s): %s\n", dumpdates, strerror(errno)); 168 (void) fclose(df); 169 msg("level %c dump on %s", level, 170 spcl.c_date == 0 ? "the epoch\n" : ctime(&spcl.c_date)); 171 } 172 173 static void 174 dumprecout(file, what) 175 FILE *file; 176 struct dumpdates *what; 177 { 178 179 if (fprintf(file, DUMPOUTFMT, 180 what->dd_name, 181 what->dd_level, 182 ctime(&what->dd_ddate)) < 0) 183 quit("%s: %s\n", dumpdates, strerror(errno)); 184 } 185 186 int recno; 187 int 188 getrecord(df, ddatep) 189 FILE *df; 190 struct dumpdates *ddatep; 191 { 192 char buf[BUFSIZ]; 193 194 recno = 0; 195 if ( (fgets(buf, BUFSIZ, df)) != buf) 196 return(-1); 197 recno++; 198 if (makedumpdate(ddatep, buf) < 0) 199 msg("Unknown intermediate format in %s, line %d\n", 200 dumpdates, recno); 201 202 #ifdef FDEBUG 203 msg("getrecord: %s %c %s", ddatep->dd_name, ddatep->dd_level, 204 ddatep->dd_ddate == 0 ? "the epoch\n" : ctime(&ddatep->dd_ddate)); 205 #endif 206 return(0); 207 } 208 209 time_t unctime(); 210 211 int 212 makedumpdate(ddp, buf) 213 struct dumpdates *ddp; 214 char *buf; 215 { 216 char un_buf[128]; 217 218 sscanf(buf, DUMPINFMT, ddp->dd_name, &ddp->dd_level, un_buf); 219 ddp->dd_ddate = unctime(un_buf); 220 if (ddp->dd_ddate < 0) 221 return(-1); 222 return(0); 223 } 224