-
Notifications
You must be signed in to change notification settings - Fork 514
/
Copy pathupdatedb.c
205 lines (178 loc) · 4.11 KB
/
updatedb.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/*
* Build database of file and directory names.
*
* Compile this file with Visual Studio and run the produced command in
* console with a directory name argument. For example, command
*
* updatedb C:\
*
* will produce the file locate.db with one file name per line such as
*
* c:\Program Files/7-Zip/7-zip.chm
* c:\Program Files/7-Zip/7-zip.dll
* c:\Program Files/7-Zip/7z.dll
* c:\Program Files/Adobe/Reader 10.0/Reader/logsession.dll
* c:\Program Files/Adobe/Reader 10.0/Reader/LogTransport2.exe
* c:\Program Files/Windows NT/Accessories/wordpad.exe
* c:\Program Files/Windows NT/Accessories/write.wpc
*
* Be ware that this file uses wide-character API which is not compatible
* with Linux or other major Unixes.
*
* Copyright (C) 1998-2019 Toni Ronkko
* This file is part of dirent. Dirent may be freely distributed
* under the MIT license. For all details and documentation, see
* https://github.com/tronkko/dirent
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#ifdef WIN32
# include <io.h>
# include <fcntl.h>
#endif
#include <dirent.h>
/* File name and location of database file */
#define DB_LOCATION L"locate.db"
/* Forward-decl */
static int update_directory(const wchar_t *dirname);
static void db_open(void);
static void db_close(void);
static void db_store(const wchar_t *dirname);
/* Module local variables */
static FILE *db = NULL;
#ifdef _MSC_VER
int
wmain(int argc, wchar_t *argv[])
{
/* Prepare for unicode output */
_setmode(_fileno(stdout), _O_U16TEXT);
/* Open locate.db */
db_open();
/* For each directory in command line */
int i = 1;
while (i < argc) {
/* Scan directory for files */
int ok = update_directory(argv[i]);
if (!ok) {
wprintf(L"Cannot open directory %s\n", argv[i]);
exit(EXIT_FAILURE);
}
i++;
}
/* Use current working directory if no arguments on command line */
if (argc == 1)
update_directory(L".");
db_close();
return EXIT_SUCCESS;
}
#else
int
main(int argc, char *argv[])
{
printf("updatedb only works on Microsoft Windows\n");
return EXIT_SUCCESS;
}
#endif
/* Find files recursively */
static int
update_directory(const wchar_t *dirname)
{
#ifdef WIN32
wchar_t buffer[PATH_MAX + 2];
wchar_t *p = buffer;
wchar_t *end = &buffer[PATH_MAX];
/* Copy directory name to buffer */
const wchar_t *src = dirname;
while (p < end && *src != '\0') {
*p++ = *src++;
}
*p = '\0';
/* Open directory stream */
_WDIR *dir = _wopendir(dirname);
if (!dir) {
/* Cannot open directory */
return /*failure*/ 0;
}
/* Print all files and directories within the directory */
struct _wdirent *ent;
while ((ent = _wreaddir (dir)) != NULL) {
wchar_t *q = p;
wchar_t c;
/* Get final character of directory name */
if (buffer < q)
c = q[-1];
else
c = ':';
/* Append directory separator if not already there */
if (c != ':' && c != '/' && c != '\\')
*q++ = '/';
/* Append file name */
src = ent->d_name;
while (q < end && *src != '\0') {
*q++ = *src++;
}
*q = '\0';
/* Decide what to do with the directory entry */
switch (ent->d_type) {
case DT_REG:
/* Store file name */
db_store(buffer);
break;
case DT_DIR:
/* Scan sub-directory recursively */
if (wcscmp(ent->d_name, L".") != 0
&& wcscmp(ent->d_name, L"..") != 0) {
update_directory(buffer);
}
break;
default:
/* Do not device entries */
/*NOP*/;
}
}
wclosedir(dir);
return /*success*/ 1;
#else
return /*failure*/ 0;
#endif
}
/* Store file name to locate.db */
static void
db_store(const wchar_t *dirname)
{
#ifdef WIN32
if (!db) {
wprintf(L"Database not open\n");
exit(EXIT_FAILURE);
}
/* Output line to file */
fwprintf(db, L"%s\n", dirname);
#endif
}
/* Open database file locate.db */
static void
db_open(void)
{
#ifdef WIN32
if (db)
return;
/* Open file for writing */
errno_t error = _wfopen_s(&db, DB_LOCATION, L"wt, ccs=UNICODE");
if (error) {
wprintf(L"Cannot open %s\n", DB_LOCATION);
exit(EXIT_FAILURE);
}
#endif
}
/* Close database file */
static void
db_close(void)
{
if (!db)
return;
/* Close file */
fclose(db);
db = NULL;
}