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