xref: /original-bsd/sbin/dump/itime.c (revision ec9268c1)
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