GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/dump/itime.c Lines: 19 108 17.6 %
Date: 2017-11-07 Branches: 5 72 6.9 %

Line Branch Exec Source
1
/*	$OpenBSD: itime.c,v 1.23 2015/12/22 21:03:58 mmcc Exp $	*/
2
/*	$NetBSD: itime.c,v 1.4 1997/04/15 01:09:50 lukem Exp $	*/
3
4
/*-
5
 * Copyright (c) 1980, 1993
6
 *	The Regents of the University of California.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the University nor the names of its contributors
17
 *    may be used to endorse or promote products derived from this software
18
 *    without specific prior written permission.
19
 *
20
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
33
#include <sys/param.h>	/* MAXBSIZE */
34
#include <sys/time.h>
35
#include <ufs/ufs/dinode.h>
36
37
#include <protocols/dumprestore.h>
38
39
#include <errno.h>
40
#include <fcntl.h>
41
#include <stdio.h>
42
#include <time.h>
43
#include <stdlib.h>
44
#include <string.h>
45
#include <unistd.h>
46
#include <limits.h>
47
48
#include "dump.h"
49
50
struct	dumpdates **ddatev = NULL;
51
int	nddates = 0;
52
int	ddates_in = 0;
53
struct	dumptime *dthead = NULL;
54
55
static	void dumprecout(FILE *, struct dumpdates *);
56
static	int getrecord(FILE *, struct dumpdates *);
57
static	int makedumpdate(struct dumpdates *, char *);
58
static	void readdumptimes(FILE *);
59
60
void
61
initdumptimes(void)
62
{
63
	FILE *df;
64
65
2
	if ((df = fopen(dumpdates, "r")) == NULL) {
66
		if (errno != ENOENT) {
67
			quit("cannot read %s: %s\n", dumpdates,
68
			    strerror(errno));
69
			/* NOTREACHED */
70
		}
71
		/*
72
		 * Dumpdates does not exist, make an empty one.
73
		 */
74
		msg("WARNING: no file `%s', making an empty one\n", dumpdates);
75
		if ((df = fopen(dumpdates, "w")) == NULL) {
76
			quit("cannot create %s: %s\n", dumpdates,
77
			    strerror(errno));
78
			/* NOTREACHED */
79
		}
80
		(void) fclose(df);
81
		if ((df = fopen(dumpdates, "r")) == NULL) {
82
			quit("cannot read %s even after creating it: %s\n",
83
			    dumpdates, strerror(errno));
84
			/* NOTREACHED */
85
		}
86
	}
87
3
	(void) flock(fileno(df), LOCK_SH);
88
1
	readdumptimes(df);
89
1
	(void) fclose(df);
90
1
}
91
92
static void
93
readdumptimes(FILE *df)
94
{
95
	int i;
96
	struct	dumptime *dtwalk;
97
98
2
	for (;;) {
99
1
		dtwalk = calloc(1, sizeof(struct dumptime));
100
1
		if (getrecord(df, &(dtwalk->dt_value)) < 0) {
101
1
			free(dtwalk);
102
			break;
103
		}
104
		nddates++;
105
		dtwalk->dt_next = dthead;
106
		dthead = dtwalk;
107
	}
108
109
1
	ddates_in = 1;
110
	/*
111
	 *	arrayify the list, leaving enough room for the additional
112
	 *	record that we may have to add to the ddate structure
113
	 */
114
1
	ddatev = calloc((unsigned) (nddates + 1), sizeof(struct dumpdates *));
115
1
	dtwalk = dthead;
116
2
	for (i = nddates - 1; i >= 0; i--, dtwalk = dtwalk->dt_next)
117
		ddatev[i] = &dtwalk->dt_value;
118
1
}
119
120
void
121
getdumptime(void)
122
{
123
	struct dumpdates *ddp;
124
	int i;
125
	char *fname;
126
127
	fname = duid ? duid : disk;
128
#ifdef FDEBUG
129
	msg("Looking for name %s in dumpdates = %s for level = %c\n",
130
		fname, dumpdates, level);
131
#endif
132
	spcl.c_ddate = 0;
133
	lastlevel = '0';
134
135
	initdumptimes();
136
	/*
137
	 *	Go find the entry with the same name for a lower increment
138
	 *	and older date
139
	 */
140
	ITITERATE(i, ddp) {
141
		if ((strncmp(fname, ddp->dd_name, sizeof(ddp->dd_name)) != 0) &&
142
		    (strncmp(disk, ddp->dd_name, sizeof(ddp->dd_name)) != 0))
143
			continue;
144
		if (ddp->dd_level >= level)
145
			continue;
146
		if (ddp->dd_ddate <= (time_t)spcl.c_ddate)
147
			continue;
148
		spcl.c_ddate = (int64_t)ddp->dd_ddate;
149
		lastlevel = ddp->dd_level;
150
	}
151
}
152
153
void
154
putdumptime(void)
155
{
156
	FILE *df;
157
	struct dumpdates *dtwalk;
158
	int fd, i;
159
	char *fname;
160
	time_t t;
161
162
	if(uflag == 0)
163
		return;
164
	if ((df = fopen(dumpdates, "r+")) == NULL)
165
		quit("cannot rewrite %s: %s\n", dumpdates, strerror(errno));
166
	fd = fileno(df);
167
	(void) flock(fd, LOCK_EX);
168
	fname = duid ? duid : disk;
169
	free(ddatev);
170
	ddatev = NULL;
171
	nddates = 0;
172
	dthead = NULL;
173
	ddates_in = 0;
174
	readdumptimes(df);
175
	if (fseek(df, 0L, SEEK_SET) < 0)
176
		quit("fseek: %s\n", strerror(errno));
177
	spcl.c_ddate = 0;
178
	ITITERATE(i, dtwalk) {
179
		if ((strncmp(fname, dtwalk->dd_name,
180
			     sizeof(dtwalk->dd_name)) != 0) &&
181
		    (strncmp(disk, dtwalk->dd_name,
182
			     sizeof(dtwalk->dd_name)) != 0))
183
			continue;
184
		if (dtwalk->dd_level != level)
185
			continue;
186
		goto found;
187
	}
188
	/*
189
	 *	construct the new upper bound;
190
	 *	Enough room has been allocated.
191
	 */
192
	dtwalk = ddatev[nddates] = calloc(1, sizeof(struct dumpdates));
193
	nddates += 1;
194
  found:
195
	(void) strlcpy(dtwalk->dd_name, fname, sizeof(dtwalk->dd_name));
196
	dtwalk->dd_level = level;
197
	dtwalk->dd_ddate = (time_t)spcl.c_date;
198
199
	ITITERATE(i, dtwalk) {
200
		dumprecout(df, dtwalk);
201
	}
202
	if (fflush(df))
203
		quit("%s: %s\n", dumpdates, strerror(errno));
204
	if (ftruncate(fd, ftello(df)))
205
		quit("ftruncate (%s): %s\n", dumpdates, strerror(errno));
206
	(void) fclose(df);
207
	t = (time_t)spcl.c_date;
208
	msg("level %c dump on %s", level, t == 0 ? "the epoch\n" : ctime(&t));
209
}
210
211
static void
212
dumprecout(FILE *file, struct dumpdates *what)
213
{
214
215
	if (fprintf(file, DUMPOUTFMT,
216
		    what->dd_name,
217
		    what->dd_level,
218
		    ctime(&what->dd_ddate)) < 0)
219
		quit("%s: %s\n", dumpdates, strerror(errno));
220
}
221
222
int	recno;
223
224
static int
225
getrecord(FILE *df, struct dumpdates *ddatep)
226
{
227
2
	char tbuf[BUFSIZ];
228
229
1
	recno = 0;
230
1
	if (fgets(tbuf, sizeof(tbuf), df) == NULL)
231
1
		return(-1);
232
	recno++;
233
	if (makedumpdate(ddatep, tbuf) < 0)
234
		msg("Unknown intermediate format in %s, line %d\n",
235
			dumpdates, recno);
236
237
#ifdef FDEBUG
238
	msg("getrecord: %s %c %s", ddatep->dd_name, ddatep->dd_level,
239
	    ddatep->dd_ddate == 0 ? "the epoch\n" : ctime(&ddatep->dd_ddate));
240
#endif
241
	return(0);
242
1
}
243
244
static int
245
makedumpdate(struct dumpdates *ddp, char *tbuf)
246
{
247
	char un_buf[BUFSIZ], *str;
248
	struct tm then;
249
250
	if (sscanf(tbuf, DUMPINFMT, ddp->dd_name, &ddp->dd_level, un_buf) != 3)
251
		return(-1);
252
	str = getduid(ddp->dd_name);
253
	if (str != NULL) {
254
		strlcpy(ddp->dd_name, str, sizeof(ddp->dd_name));
255
		free(str);
256
	}
257
	str = strptime(un_buf, "%a %b %e %H:%M:%S %Y", &then);
258
	then.tm_isdst = -1;
259
	if (str == NULL || (*str != '\n' && *str != '\0'))
260
		ddp->dd_ddate = (time_t) -1;
261
	else
262
		ddp->dd_ddate = mktime(&then);
263
	if (ddp->dd_ddate < 0)
264
		return(-1);
265
	return(0);
266
}