/* * 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 #include #include #include #ifdef WIN32 # include # include #endif #include /* 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; } }