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