1*22036Sdist /* 2*22036Sdist * Copyright (c) 1980 Regents of the University of California. 3*22036Sdist * All rights reserved. The Berkeley software License Agreement 4*22036Sdist * specifies the terms and conditions for redistribution. 5*22036Sdist */ 612589Smckusick 7*22036Sdist #ifndef lint 8*22036Sdist static char sccsid[] = "@(#)itime.c 5.1 (Berkeley) 06/05/85"; 9*22036Sdist #endif not lint 10*22036Sdist 111422Sroot #include "dump.h" 1212589Smckusick #include <sys/file.h> 131422Sroot 141422Sroot char *prdate(d) 151422Sroot time_t d; 161422Sroot { 171422Sroot char *p; 181422Sroot 191422Sroot if(d == 0) 201422Sroot return("the epoch"); 211422Sroot p = ctime(&d); 221422Sroot p[24] = 0; 231422Sroot return(p); 241422Sroot } 251422Sroot 261422Sroot struct idates **idatev = 0; 271422Sroot int nidates = 0; 281422Sroot int idates_in = 0; 291422Sroot struct itime *ithead = 0; 301422Sroot 311422Sroot inititimes() 321422Sroot { 331422Sroot FILE *df; 341422Sroot register int i; 351422Sroot register struct itime *itwalk; 3612589Smckusick int fd; 371422Sroot 381422Sroot if (idates_in) 391422Sroot return; 4013151Ssam fd = open(increm, O_RDONLY); 4113151Ssam if (fd < 0) { 4212589Smckusick perror(increm); 4312589Smckusick return; 4412589Smckusick } 4513151Ssam (void) flock(fd, LOCK_SH); 4612589Smckusick if ((df = fdopen(fd, "r")) == NULL) { 471422Sroot nidates = 0; 481422Sroot ithead = 0; 491422Sroot } else { 501422Sroot do{ 511422Sroot itwalk=(struct itime *)calloc(1,sizeof (struct itime)); 521422Sroot if (getrecord(df, &(itwalk->it_value)) < 0) 531422Sroot break; 541422Sroot nidates++; 551422Sroot itwalk->it_next = ithead; 561422Sroot ithead = itwalk; 571422Sroot } while (1); 581422Sroot fclose(df); 591422Sroot } 601422Sroot 611422Sroot idates_in = 1; 621422Sroot /* 631422Sroot * arrayify the list, leaving enough room for the additional 641422Sroot * record that we may have to add to the idate structure 651422Sroot */ 661422Sroot idatev = (struct idates **)calloc(nidates + 1,sizeof (struct idates *)); 671422Sroot for (i = nidates-1, itwalk = ithead; i >= 0; i--, itwalk = itwalk->it_next) 681422Sroot idatev[i] = &itwalk->it_value; 691422Sroot } 701422Sroot 711422Sroot getitime() 721422Sroot { 731422Sroot register struct idates *ip; 741422Sroot register int i; 751422Sroot char *fname; 761422Sroot 771422Sroot fname = disk; 781422Sroot #ifdef FDEBUG 791422Sroot msg("Looking for name %s in increm = %s for delta = %c\n", 801422Sroot fname, increm, incno); 811422Sroot #endif 821422Sroot spcl.c_ddate = 0; 8314964Smckusick lastincno = '0'; 841422Sroot 851422Sroot inititimes(); 861422Sroot /* 871422Sroot * Go find the entry with the same name for a lower increment 881422Sroot * and older date 891422Sroot */ 901422Sroot ITITERATE(i, ip){ 911422Sroot if(strncmp(fname, ip->id_name, 921422Sroot sizeof (ip->id_name)) != 0) 931422Sroot continue; 941422Sroot if (ip->id_incno >= incno) 951422Sroot continue; 961422Sroot if (ip->id_ddate <= spcl.c_ddate) 971422Sroot continue; 981422Sroot spcl.c_ddate = ip->id_ddate; 9912947Smckusick lastincno = ip->id_incno; 1001422Sroot } 1011422Sroot } 1021422Sroot 1031422Sroot putitime() 1041422Sroot { 1051422Sroot FILE *df; 1061422Sroot register struct idates *itwalk; 1071422Sroot register int i; 10812589Smckusick int fd; 1091422Sroot char *fname; 1101422Sroot 1111422Sroot if(uflag == 0) 1121422Sroot return; 11313151Ssam fd = open(temp, O_RDWR|O_CREAT, 0600); 11413151Ssam if (fd < 0) { 11512589Smckusick perror(temp); 11612589Smckusick dumpabort(); 11712589Smckusick } 11813151Ssam (void) flock(fd, LOCK_EX); 11912589Smckusick if ((df = fdopen(fd, "w")) == NULL) { 12012589Smckusick perror(temp); 12112589Smckusick dumpabort(); 12212589Smckusick } 1231422Sroot fname = disk; 12412584Smckusick free(idatev); 12512584Smckusick idatev = 0; 12612584Smckusick nidates = 0; 12712584Smckusick ithead = 0; 12812584Smckusick idates_in = 0; 12912584Smckusick inititimes(); 1301422Sroot 1311422Sroot spcl.c_ddate = 0; 1321422Sroot ITITERATE(i, itwalk){ 1331422Sroot if (strncmp(fname, itwalk->id_name, 1341422Sroot sizeof (itwalk->id_name)) != 0) 1351422Sroot continue; 1361422Sroot if (itwalk->id_incno != incno) 1371422Sroot continue; 1381422Sroot goto found; 1391422Sroot } 1401422Sroot /* 1411422Sroot * construct the new upper bound; 1421422Sroot * Enough room has been allocated. 1431422Sroot */ 1441422Sroot itwalk = idatev[nidates] = 1451422Sroot (struct idates *)calloc(1, sizeof(struct idates)); 1461422Sroot nidates += 1; 1471422Sroot found: 1481422Sroot strncpy(itwalk->id_name, fname, sizeof (itwalk->id_name)); 1491422Sroot itwalk->id_incno = incno; 1501422Sroot itwalk->id_ddate = spcl.c_date; 1511422Sroot 1521422Sroot ITITERATE(i, itwalk){ 1531422Sroot recout(df, itwalk); 1541422Sroot } 15512589Smckusick if (rename(temp, increm) < 0) { 15612589Smckusick perror("rename"); 15712589Smckusick (void) unlink(temp); 15812589Smckusick dumpabort(); 15912589Smckusick } 16012589Smckusick (void) chmod(increm, 0644); 16112589Smckusick (void) fclose(df); 1621422Sroot msg("level %c dump on %s\n", incno, prdate(spcl.c_date)); 1631422Sroot } 1641422Sroot 1651422Sroot recout(file, what) 1661422Sroot FILE *file; 1671422Sroot struct idates *what; 1681422Sroot { 1691422Sroot fprintf(file, DUMPOUTFMT, 1701422Sroot what->id_name, 1711422Sroot what->id_incno, 1721422Sroot ctime(&(what->id_ddate)) 1731422Sroot ); 1741422Sroot } 1751422Sroot 1761422Sroot int recno; 1771422Sroot int getrecord(df, idatep) 1781422Sroot FILE *df; 1791422Sroot struct idates *idatep; 1801422Sroot { 1811422Sroot char buf[BUFSIZ]; 1821422Sroot 1831422Sroot recno = 0; 1841422Sroot if ( (fgets(buf, BUFSIZ, df)) != buf) 1851422Sroot return(-1); 1861422Sroot recno++; 1871422Sroot if (makeidate(idatep, buf) < 0) 1881422Sroot msg("Unknown intermediate format in %s, line %d\n", 18912589Smckusick increm, recno); 1901422Sroot 1911422Sroot #ifdef FDEBUG 1921422Sroot msg("getrecord: %s %c %s\n", 1931422Sroot idatep->id_name, idatep->id_incno, prdate(idatep->id_ddate)); 1941422Sroot #endif 1951422Sroot return(0); 1961422Sroot } 1971422Sroot 1981422Sroot time_t unctime(); 1991422Sroot 2001422Sroot int makeidate(ip, buf) 2011422Sroot struct idates *ip; 2021422Sroot char *buf; 2031422Sroot { 2041422Sroot char un_buf[128]; 2051422Sroot 2061422Sroot sscanf(buf, DUMPINFMT, ip->id_name, &ip->id_incno, un_buf); 2071422Sroot ip->id_ddate = unctime(un_buf); 2081422Sroot if (ip->id_ddate < 0) 2091422Sroot return(-1); 2101422Sroot return(0); 2111422Sroot } 2121422Sroot 2134701Smckusic /* 2145328Smckusic * This is an estimation of the number of TP_BSIZE blocks in the file. 21516250Smckusick * It estimates the number of blocks in files with holes by assuming 21616250Smckusick * that all of the blocks accounted for by di_blocks are data blocks 21716250Smckusick * (when some of the blocks are usually used for indirect pointers); 21816250Smckusick * hence the estimate may be high. 2194701Smckusic */ 2201422Sroot est(ip) 2211422Sroot struct dinode *ip; 2221422Sroot { 22316250Smckusick long s, t; 2241422Sroot 22516250Smckusick /* 22616250Smckusick * ip->di_size is the size of the file in bytes. 22716250Smckusick * ip->di_blocks stores the number of sectors actually in the file. 22816250Smckusick * If there are more sectors than the size would indicate, this just 22916250Smckusick * means that there are indirect blocks in the file or unused 23016250Smckusick * sectors in the last file block; we can safely ignore these 23116250Smckusick * (s = t below). 23216250Smckusick * If the file is bigger than the number of sectors would indicate, 23316250Smckusick * then the file has holes in it. In this case we must use the 23416250Smckusick * block count to estimate the number of data blocks used, but 23516250Smckusick * we use the actual size for estimating the number of indirect 23616250Smckusick * dump blocks (t vs. s in the indirect block calculation). 23716250Smckusick */ 2381422Sroot esize++; 23916250Smckusick s = howmany(dbtob(ip->di_blocks), TP_BSIZE); 24016250Smckusick t = howmany(ip->di_size, TP_BSIZE); 24116250Smckusick if ( s > t ) 24216250Smckusick s = t; 2435328Smckusic if (ip->di_size > sblock->fs_bsize * NDADDR) { 24416250Smckusick /* calculate the number of indirect blocks on the dump tape */ 24516250Smckusick s += howmany(t - NDADDR * sblock->fs_bsize / TP_BSIZE, 2465328Smckusic TP_NINDIR); 2475328Smckusic } 2481422Sroot esize += s; 2491422Sroot } 2501422Sroot 2511422Sroot bmapest(map) 2525328Smckusic char *map; 2531422Sroot { 2541422Sroot register i, n; 2551422Sroot 2561422Sroot n = -1; 2575328Smckusic for (i = 0; i < msiz; i++) 2581422Sroot if(map[i]) 2591422Sroot n = i; 2601422Sroot if(n < 0) 2611422Sroot return; 2625328Smckusic n++; 2631422Sroot esize++; 2645328Smckusic esize += howmany(n * sizeof map[0], TP_BSIZE); 2651422Sroot } 266