|
|
- /*
- * A file look-up utility to complement updatedb
- *
- * Compile and run updatedb command first to create locate.db file. Then,
- * compile this program with Visual Studio and run the program in console with
- * a file name argument. For example, the command
- *
- * locate autoexec
- *
- * might output something like
- *
- * c:/AUTOEXEC.BAT
- * c:/WINDOWS/repair/autoexec.nt
- * c:/WINDOWS/system32/AUTOEXEC.NT
- *
- * 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 db_locate (const wchar_t *pattern);
- static int db_match (const wchar_t *fn, const wchar_t *pattern);
- static void db_open (void);
- static void db_close (void);
- static int db_read (wchar_t *buffer, size_t max);
-
-
- /* Module local variables */
- static FILE *db = NULL;
-
-
- int
- main(
- int argc, char *argv[])
- {
- #ifdef WIN32
- int i;
-
- /* Prepare for unicode output */
- _setmode (_fileno (stdout), _O_U16TEXT);
-
- /* For each pattern in command line */
- i = 1;
- while (i < argc) {
- wchar_t buffer[PATH_MAX + 1];
- errno_t error;
- size_t n;
- int count = 0;
-
- /* Convert ith argument to wide-character string */
- error = mbstowcs_s (&n, buffer, PATH_MAX, argv[i], _TRUNCATE);
- if (!error) {
- /* Find files matching pattern */
- count = db_locate (buffer);
-
- /* Output warning if string is not found */
- if (count == 0) {
- wprintf (L"%s not found\n", buffer);
- }
- }
-
-
- i++;
- }
-
- if (argc < 2) {
- wprintf (L"Usage: locate pattern\n");
- exit (EXIT_FAILURE);
- }
- #else
- printf ("locate only works on Microsoft Windows\n");
- #endif
-
- return EXIT_SUCCESS;
- }
-
- /* Match pattern against files in locate.db file */
- static int
- db_locate(
- const wchar_t *pattern)
- {
- int count = 0;
-
- #ifdef WIN32
- wchar_t buffer[PATH_MAX + 1];
-
- /* Open locate.db for read */
- db_open ();
-
- /* Read one directory and file name at a time from database file */
- while (db_read (buffer, PATH_MAX + 1)) {
- /* See if file name in buffer matches the search pattern */
- if (db_match (buffer, pattern)) {
- /* Match found => output file name and path */
- wprintf (L"%s\n", buffer);
- count++;
- }
-
- }
-
- db_close ();
- #endif
-
- return count;
- }
-
- /* Match pattern against file name */
- static int
- db_match(
- const wchar_t *fn, const wchar_t *pattern)
- {
- int found = 0;
-
- #ifdef WIN32
- wchar_t *p;
- wchar_t base[PATH_MAX + 1];
- wchar_t patt[PATH_MAX + 1];
- int i;
- int done = 0;
-
- /* Locate zero-terminator from fn */
- p = wcschr (fn, '\0');
-
- /* Find base name from buffer */
- while (fn < p && !done) {
- switch (p[-1]) {
- case ':':
- case '/':
- case '\\':
- /* Final path separator found */
- done = 1;
- break;
-
- default:
- /* No path separator yet */
- p--;
- }
- }
-
- /* Convert base name to lower case */
- i = 0;
- while (i < PATH_MAX && p[i] != '\0') {
- base[i] = towlower (p[i]);
- i++;
- }
- base[i] = '\0';
-
- /* Convert search pattern to lower case */
- i = 0;
- while (i < PATH_MAX && pattern[i] != '\0') {
- patt[i] = towlower (pattern[i]);
- i++;
- }
- patt[i] = '\0';
-
- /* See if file name matches pattern */
- if (wcsstr (base, patt) != NULL) {
- found = 1;
- } else {
- found = 0;
- }
- #endif
-
- return found;
- }
-
- /*
- * Read line from locate.db. This function is same as fgetws() except
- * that new-line at the end of line is not included.
- */
- static int
- db_read(
- wchar_t *buffer, size_t max)
- {
- int ok = 0;
-
- #ifdef WIN32
- size_t i = 0;
- wchar_t c;
- int done = 0;
-
- do {
- /* Read wide-character from stream */
- if (db) {
- c = fgetwc (db);
- } else {
- wprintf (L"Database not open\n");
- exit (EXIT_SUCCESS);
- }
-
- /* Determine how to process character */
- switch (c) {
- case '\r':
- /* Ignore, should be handled by run-time libraries */
- /*NOP*/;
- break;
-
- case '\n':
- /* End of string => return file name and true */
- done = 1;
- ok = 1;
- break;
-
- case /*EOF*/WEOF:
- /* End of file */
- done = 1;
- if (i == 0) {
- /* No data in buffer => return false to indicate EOF */
- ok = 0;
- } else {
- /* Data in buffer => return true */
- ok = 1;
- }
- break;
-
- default:
- /* Store character */
- if (i < max - 1) {
- buffer[i++] = c;
- } else {
- buffer[max - 1] = '\0';
- wprintf (L"Buffer too small: %s", buffer);
- exit (EXIT_FAILURE);
- }
- }
- } while (!done);
-
- /* Zero-terminate buffer */
- buffer[i] = '\0';
- #endif
-
- return ok;
- }
-
- /* 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"rt, 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;
- }
- }
|