1 static char *sccsid = "@(#)itime.c 1.13 (Berkeley) 03/28/84"; 2 3 #include "dump.h" 4 #include <sys/file.h> 5 6 char *prdate(d) 7 time_t d; 8 { 9 char *p; 10 11 if(d == 0) 12 return("the epoch"); 13 p = ctime(&d); 14 p[24] = 0; 15 return(p); 16 } 17 18 struct idates **idatev = 0; 19 int nidates = 0; 20 int idates_in = 0; 21 struct itime *ithead = 0; 22 23 inititimes() 24 { 25 FILE *df; 26 register int i; 27 register struct itime *itwalk; 28 int fd; 29 30 if (idates_in) 31 return; 32 fd = open(increm, O_RDONLY); 33 if (fd < 0) { 34 perror(increm); 35 return; 36 } 37 (void) flock(fd, LOCK_SH); 38 if ((df = fdopen(fd, "r")) == NULL) { 39 nidates = 0; 40 ithead = 0; 41 } else { 42 do{ 43 itwalk=(struct itime *)calloc(1,sizeof (struct itime)); 44 if (getrecord(df, &(itwalk->it_value)) < 0) 45 break; 46 nidates++; 47 itwalk->it_next = ithead; 48 ithead = itwalk; 49 } while (1); 50 fclose(df); 51 } 52 53 idates_in = 1; 54 /* 55 * arrayify the list, leaving enough room for the additional 56 * record that we may have to add to the idate structure 57 */ 58 idatev = (struct idates **)calloc(nidates + 1,sizeof (struct idates *)); 59 for (i = nidates-1, itwalk = ithead; i >= 0; i--, itwalk = itwalk->it_next) 60 idatev[i] = &itwalk->it_value; 61 } 62 63 getitime() 64 { 65 register struct idates *ip; 66 register int i; 67 char *fname; 68 69 fname = disk; 70 #ifdef FDEBUG 71 msg("Looking for name %s in increm = %s for delta = %c\n", 72 fname, increm, incno); 73 #endif 74 spcl.c_ddate = 0; 75 lastincno = '0'; 76 77 inititimes(); 78 /* 79 * Go find the entry with the same name for a lower increment 80 * and older date 81 */ 82 ITITERATE(i, ip){ 83 if(strncmp(fname, ip->id_name, 84 sizeof (ip->id_name)) != 0) 85 continue; 86 if (ip->id_incno >= incno) 87 continue; 88 if (ip->id_ddate <= spcl.c_ddate) 89 continue; 90 spcl.c_ddate = ip->id_ddate; 91 lastincno = ip->id_incno; 92 } 93 } 94 95 putitime() 96 { 97 FILE *df; 98 register struct idates *itwalk; 99 register int i; 100 int fd; 101 char *fname; 102 103 if(uflag == 0) 104 return; 105 fd = open(temp, O_RDWR|O_CREAT, 0600); 106 if (fd < 0) { 107 perror(temp); 108 dumpabort(); 109 } 110 (void) flock(fd, LOCK_EX); 111 if ((df = fdopen(fd, "w")) == NULL) { 112 perror(temp); 113 dumpabort(); 114 } 115 fname = disk; 116 free(idatev); 117 idatev = 0; 118 nidates = 0; 119 ithead = 0; 120 idates_in = 0; 121 inititimes(); 122 123 spcl.c_ddate = 0; 124 ITITERATE(i, itwalk){ 125 if (strncmp(fname, itwalk->id_name, 126 sizeof (itwalk->id_name)) != 0) 127 continue; 128 if (itwalk->id_incno != incno) 129 continue; 130 goto found; 131 } 132 /* 133 * construct the new upper bound; 134 * Enough room has been allocated. 135 */ 136 itwalk = idatev[nidates] = 137 (struct idates *)calloc(1, sizeof(struct idates)); 138 nidates += 1; 139 found: 140 strncpy(itwalk->id_name, fname, sizeof (itwalk->id_name)); 141 itwalk->id_incno = incno; 142 itwalk->id_ddate = spcl.c_date; 143 144 ITITERATE(i, itwalk){ 145 recout(df, itwalk); 146 } 147 if (rename(temp, increm) < 0) { 148 perror("rename"); 149 (void) unlink(temp); 150 dumpabort(); 151 } 152 (void) chmod(increm, 0644); 153 (void) fclose(df); 154 msg("level %c dump on %s\n", incno, prdate(spcl.c_date)); 155 } 156 157 recout(file, what) 158 FILE *file; 159 struct idates *what; 160 { 161 fprintf(file, DUMPOUTFMT, 162 what->id_name, 163 what->id_incno, 164 ctime(&(what->id_ddate)) 165 ); 166 } 167 168 int recno; 169 int getrecord(df, idatep) 170 FILE *df; 171 struct idates *idatep; 172 { 173 char buf[BUFSIZ]; 174 175 recno = 0; 176 if ( (fgets(buf, BUFSIZ, df)) != buf) 177 return(-1); 178 recno++; 179 if (makeidate(idatep, buf) < 0) 180 msg("Unknown intermediate format in %s, line %d\n", 181 increm, recno); 182 183 #ifdef FDEBUG 184 msg("getrecord: %s %c %s\n", 185 idatep->id_name, idatep->id_incno, prdate(idatep->id_ddate)); 186 #endif 187 return(0); 188 } 189 190 time_t unctime(); 191 192 int makeidate(ip, buf) 193 struct idates *ip; 194 char *buf; 195 { 196 char un_buf[128]; 197 198 sscanf(buf, DUMPINFMT, ip->id_name, &ip->id_incno, un_buf); 199 ip->id_ddate = unctime(un_buf); 200 if (ip->id_ddate < 0) 201 return(-1); 202 return(0); 203 } 204 205 /* 206 * This is an estimation of the number of TP_BSIZE blocks in the file. 207 * It estimates the number of blocks in files with holes by assuming 208 * that all of the blocks accounted for by di_blocks are data blocks 209 * (when some of the blocks are usually used for indirect pointers); 210 * hence the estimate may be high. 211 */ 212 est(ip) 213 struct dinode *ip; 214 { 215 long s, t; 216 217 /* 218 * ip->di_size is the size of the file in bytes. 219 * ip->di_blocks stores the number of sectors actually in the file. 220 * If there are more sectors than the size would indicate, this just 221 * means that there are indirect blocks in the file or unused 222 * sectors in the last file block; we can safely ignore these 223 * (s = t below). 224 * If the file is bigger than the number of sectors would indicate, 225 * then the file has holes in it. In this case we must use the 226 * block count to estimate the number of data blocks used, but 227 * we use the actual size for estimating the number of indirect 228 * dump blocks (t vs. s in the indirect block calculation). 229 */ 230 esize++; 231 s = howmany(dbtob(ip->di_blocks), TP_BSIZE); 232 t = howmany(ip->di_size, TP_BSIZE); 233 if ( s > t ) 234 s = t; 235 if (ip->di_size > sblock->fs_bsize * NDADDR) { 236 /* calculate the number of indirect blocks on the dump tape */ 237 s += howmany(t - NDADDR * sblock->fs_bsize / TP_BSIZE, 238 TP_NINDIR); 239 } 240 esize += s; 241 } 242 243 bmapest(map) 244 char *map; 245 { 246 register i, n; 247 248 n = -1; 249 for (i = 0; i < msiz; i++) 250 if(map[i]) 251 n = i; 252 if(n < 0) 253 return; 254 n++; 255 esize++; 256 esize += howmany(n * sizeof map[0], TP_BSIZE); 257 } 258