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