/*
|
|
* An example demonstrating wide-character functions
|
|
*
|
|
* 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;
|
|
|
|
|
|
int
|
|
main(
|
|
int argc, char *argv[])
|
|
{
|
|
#ifdef WIN32
|
|
int i;
|
|
int ok;
|
|
|
|
/* Prepare for unicode output */
|
|
_setmode (_fileno (stdout), _O_U16TEXT);
|
|
|
|
/* Open locate.db */
|
|
db_open ();
|
|
|
|
/* For each directory in command line */
|
|
i = 1;
|
|
while (i < argc) {
|
|
wchar_t buffer[PATH_MAX + 1];
|
|
errno_t error;
|
|
size_t n;
|
|
|
|
/* Convert ith argument to wide-character string */
|
|
error = mbstowcs_s (&n, buffer, PATH_MAX, argv[i], _TRUNCATE);
|
|
if (!error) {
|
|
|
|
/* Scan directory for files */
|
|
ok = update_directory (buffer);
|
|
if (!ok) {
|
|
wprintf (L"Cannot open directory %s\n", buffer);
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
/* Use current working directory if no arguments on command line */
|
|
if (argc == 1) {
|
|
update_directory (L".");
|
|
}
|
|
|
|
db_close ();
|
|
#else
|
|
printf ("updatedb only works on Microsoft Windows\n");
|
|
#endif
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
|
|
/* Find files recursively */
|
|
static int
|
|
update_directory(
|
|
const wchar_t *dirname)
|
|
{
|
|
int ok = 0;
|
|
|
|
#ifdef WIN32
|
|
_WDIR *dir;
|
|
wchar_t buffer[PATH_MAX + 2];
|
|
wchar_t *p = buffer;
|
|
const wchar_t *src;
|
|
wchar_t *end = &buffer[PATH_MAX];
|
|
|
|
/* Copy directory name to buffer */
|
|
src = dirname;
|
|
while (p < end && *src != '\0') {
|
|
*p++ = *src++;
|
|
}
|
|
*p = '\0';
|
|
|
|
/* Open directory stream */
|
|
dir = _wopendir (dirname);
|
|
if (dir != NULL) {
|
|
struct _wdirent *ent;
|
|
|
|
/* Print all files and directories within the directory */
|
|
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);
|
|
ok = 1;
|
|
|
|
} else {
|
|
|
|
/* Cannot open directory */
|
|
ok = 0;
|
|
|
|
}
|
|
#endif
|
|
|
|
return ok;
|
|
}
|
|
|
|
/* Store file name to locate.db */
|
|
static void
|
|
db_store(
|
|
const wchar_t *dirname)
|
|
{
|
|
#ifdef WIN32
|
|
if (db) {
|
|
/* Output line to file */
|
|
fwprintf (db, L"%s\n", dirname);
|
|
} else {
|
|
wprintf (L"Database not open\n");
|
|
exit (EXIT_FAILURE);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/* Open database file locate.db */
|
|
static void
|
|
db_open(
|
|
void)
|
|
{
|
|
#ifdef WIN32
|
|
if (db == NULL) {
|
|
errno_t error;
|
|
|
|
/* Open file for writing */
|
|
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) {
|
|
fclose (db);
|
|
db = NULL;
|
|
}
|
|
}
|