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