Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 4972 → Rev 4973

/programs/develop/libraries/menuetlibc/src/libc/dos/dir/ftreewlk.c
0,0 → 1,171
/* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
/*
* Recursively descent the directory hierarchy rooted in DIR,
* calling FUNC for each object in the hierarchy. We cannot
* use ftw(), because it uses some non-ANSI functions which
* will pollute ANSI namespace, while we need this function
* in some ANSI functions (e.g., rename()). Thus, this function
* is closely modeled on ftw(), but uses DOS directory search
* functions and structures instead of opendir()/readdir()/stat().
*
* Copyright (c) 1995 Eli Zaretskii <eliz@is.elta.co.il>
*
* This software may be used freely as long as this copyright notice is
* left intact. There is no warranty on this software.
*
*/
 
#include <libc/stubs.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <dir.h>
 
#define FA_ALL (FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_LABEL|FA_DIREC|FA_ARCH)
 
int
__file_tree_walk(const char *dir,
int (*func)(const char *, const struct ffblk *))
{
struct ffblk ff;
unsigned char searchspec[FILENAME_MAX];
unsigned char found[FILENAME_MAX], *dir_end;
int e = errno;
 
if (dir == 0 || func == 0)
{
errno = EFAULT;
return -1;
}
 
if (*dir == '\0')
{
errno = ENOENT;
return -1;
}
 
/* Construct the search spec for findfirst(). Treat ``d:'' as ``d:.''. */
strcpy(searchspec, dir);
dir_end = searchspec + strlen(searchspec) - 1;
if (*dir_end == ':')
{
*++dir_end = '.';
*++dir_end = '\0';
}
else if (*dir_end == '/' || *dir_end == '\\')
*dir_end = '\0';
else
++dir_end;
strcpy(dir_end, "/*.*");
 
/* Prepare the buffer where the full pathname of the found files
will be placed. */
strcpy(found, dir);
dir_end = found + strlen(found) - 1;
if (*dir_end == ':')
{
*++dir_end = '.';
dir_end[1] = '\0';
}
if (*dir_end != '/' && *dir_end != '\\')
{
/* Try to preserve user's forward/backward slash style. */
*++dir_end = strchr(found, '\\') == 0 ? '/': '\\';
*++dir_end = '\0';
}
else
++dir_end;
 
if (findfirst(searchspec, &ff, FA_ALL))
return -1;
 
do
{
int func_result;
unsigned char *p = dir_end;
 
/* Skip `.' and `..' entries. */
if (ff.ff_name[0] == '.' &&
(ff.ff_name[1] == '\0' || ff.ff_name[1] == '.'))
continue;
 
/* Construct full pathname in FOUND[]. */
strcpy(dir_end, ff.ff_name);
 
/* Convert name of found file to lower-case. Cannot use
strlwr() because it's non-ANSI. Sigh... */
while (*p)
*p++ = tolower(*p);
 
/* Invoke FUNC() on this file. */
if ((func_result = (*func)(found, &ff)) != 0)
return func_result;
 
/* If this is a directory, walk its siblings. */
if (ff.ff_attrib & 0x10)
{
int subwalk_result;
 
if ((subwalk_result = __file_tree_walk(found, func)) != 0)
return subwalk_result;
}
} while (findnext(&ff) == 0);
 
if (errno == ENMFILE) /* normal case: tree exhausted */
{
errno = e; /* restore errno from previous syscall */
return 0;
}
 
return -1; /* error; errno set by findnext() */
}
 
#ifdef TEST
 
#include <stdlib.h>
 
int
ff_walker(const char *path, const struct ffblk *ff)
{
printf("%s:\t%lu\t", path, ff->ff_fsize);
if (ff->ff_attrib & 1)
printf("R");
if (ff->ff_attrib & 2)
printf("H");
if (ff->ff_attrib & 4)
printf("S");
if (ff->ff_attrib & 8)
printf("V");
if (ff->ff_attrib & 0x10)
printf("D");
if (ff->ff_attrib & 0x20)
printf("A");
printf("\n");
 
if (strcmp(ff->ff_name, "XXXXX") == 0)
return 8;
return 0;
}
 
int
main(int argc, char *argv[])
{
if (argc > 1)
{
char msg[80];
 
sprintf(msg, "file_tree_walk: %d",
file_tree_walk(argv[1], ff_walker));
if (errno)
perror(msg);
else
puts(msg);
}
else
printf("Usage: %s dir\n", argv[0]);
 
return 0;
}
 
#endif