1 /* $NetBSD: dev_mkdb.c,v 1.26 2008/12/28 21:39:35 christos Exp $ */
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
32 #include <sys/cdefs.h>
34 __COPYRIGHT("@(#) Copyright (c) 1990, 1993\
35 The Regents of the University of California. All rights reserved.");
40 static char sccsid
[] = "from: @(#)dev_mkdb.c 8.1 (Berkeley) 6/6/93";
42 __RCSID("$NetBSD: dev_mkdb.c,v 1.26 2008/12/28 21:39:35 christos Exp $");
46 #include <sys/param.h>
62 static void usage(void) __unused
;
68 2048 * 1024, /* cachesize */
74 main(int argc
, char **argv
)
86 char buf
[MAXPATHLEN
+ 1];
87 char dbtmp
[MAXPATHLEN
+ 1];
88 char dbname
[MAXPATHLEN
+ 1];
89 char *dbname_arg
= NULL
;
91 char path_dev
[MAXPATHLEN
+ 1] = _PATH_DEV
;
92 char cur_dir
[MAXPATHLEN
+ 1];
99 while ((ch
= getopt(argc
, argv
, "o:")) != -1)
112 if (strlcpy(path_dev
, argv
[0], sizeof(path_dev
)) >=
114 errx(1, "device path too long");
119 if (getcwd(cur_dir
, sizeof(cur_dir
)) == NULL
)
120 err(1, "%s", cur_dir
);
122 if (chdir(path_dev
) == -1)
123 err(1, "%s", path_dev
);
127 dlen
= strlen(path_dev
) - 1;
128 ftsp
= fts_open(pathv
, FTS_PHYSICAL
, NULL
);
130 err(1, "fts_open: %s", path_dev
);
132 if (chdir(cur_dir
) == -1)
133 err(1, "%s", cur_dir
);
136 if (strlcpy(dbname
, dbname_arg
, sizeof(dbname
)) >=
138 errx(1, "dbname too long");
140 if (snprintf(dbname
, sizeof(dbname
), "%sdev.db",
141 _PATH_VARRUN
) >= (int)sizeof(dbname
))
142 errx(1, "dbname too long");
145 * We use rename() to produce the dev.db file from a temporary file,
146 * and rename() is not able to move files across filesystems. Hence we
147 * need the temporary file to be in the same directory as dev.db.
149 * Additionally, we might be working in a world writable directory,
150 * we must ensure that we are not opening an existing file, therefore
151 * the loop on dbopen.
153 (void)strlcpy(dbtmp
, dbname
, sizeof(dbtmp
));
154 q
= dbtmp
+ strlen(dbtmp
);
156 (void)gettimeofday(&tv
, NULL
);
157 (void)snprintf(q
, sizeof(dbtmp
) - (q
- dbtmp
),
158 "%ld.tmp", (long)tv
.tv_usec
);
159 db
= dbopen(dbtmp
, O_CREAT
|O_EXCL
|O_EXLOCK
|O_RDWR
|O_TRUNC
,
160 S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IROTH
, DB_HASH
, &openinfo
);
161 } while (!db
&& (errno
== EEXIST
));
166 * Keys are a mode_t followed by a dev_t. The former is the type of
167 * the file (mode & S_IFMT), the latter is the st_rdev field. Note
168 * that the structure may contain padding, so we have to clear it
171 (void)memset(&bkey
, 0, sizeof(bkey
));
173 key
.size
= sizeof(bkey
);
174 data
.data
= (u_char
*)(void *)buf
;
175 while ((p
= fts_read(ftsp
)) != NULL
) {
176 switch (p
->fts_info
) {
184 /* Create the key. */
185 if (S_ISCHR(st
->st_mode
))
187 else if (S_ISBLK(st
->st_mode
))
191 bkey
.dev
= st
->st_rdev
;
194 * Create the data; nul terminate the name so caller doesn't
195 * have to. Skip path_dev and slash. Handle old versions
196 * of fts(3), that added multiple slashes, if the pathname
197 * ended with a slash.
199 while (p
->fts_path
[dlen
] == '/')
201 (void)strlcpy(buf
, p
->fts_path
+ dlen
, sizeof(buf
));
202 data
.size
= p
->fts_pathlen
- dlen
+ 1;
203 if ((*db
->put
)(db
, &key
, &data
, 0))
204 err(1, "dbput %s", dbtmp
);
206 (void)(*db
->close
)(db
);
207 (void)fts_close(ftsp
);
209 if (chdir(cur_dir
) == -1)
210 err(1, "%s", cur_dir
);
211 if (rename(dbtmp
, dbname
) == -1)
212 err(1, "rename %s to %s", dbtmp
, dbname
);
220 (void)fprintf(stderr
, "Usage: %s [-o database] [directory]\n",