dir.c 4.15 KB
/*
 * dir.c: This is the home of the windows-style get_dir_first, get_dir_next.
 *        Right now, those function only return non-directory filenames.
 *        (This is because thats what i wanted for checkout_files.)
 *
 *        Windows has no real directory functions...
 *        (i guess that's because win does not organize directories as files)
 *        so what it does is, it simply applies
 *        a valid filepattern and fires FindFirstFile, which finds the
 *        first file that fits to that pattern.
 *        After that FindNextFile is used with the handle that FindFirstFile
 *        returned to get more files that fit to that pattern.
 *
 * Copyright (C) 2006 Georg Steffers
 *
 * Author:    Georg Steffers [GST] <georg.steffers@aschendorff.de>
 * Developer:
 *
 * Changes (for this file only):
 *   (2006-06-12) [GST] Started this changelog...well the program is
 *                      ready since some weeks right now.
 */
#include <unistd.h>
#include <string.h>
#include <errno.h>

#include <scot/dir.h>
#include <scot/memory.h>


/*
 * This functions tries an opendir on the given path and uses the
 * get_dir_next function to retrieve the first file within that directory.
 *
 * parameters:
 *   path: The path to the directory that should be read.
 *   file: A pointer to a structure that holds further information to the
 *         found file. (e.g. the path to the file)
 *   fsym: this has actually no meaning on win32 systems.
 *
 * returns:
 *   NULL if an error occures or an handle to the opened directory on
 *   success. This handle should be closed later in the program.
 *   There should be a function that does this, but as this program
 *   actually exits anyway after directory reading i have not done it
 *   right now.
 */
DIR_HANDLE
get_dir_first (const char * path, FILE_DATA * file, int fsym)
{
	TCHAR  pattern[MAX_PATH+1];
	HANDLE dir;

	SCOT_STRN_COPY (pattern, path, MAX_PATH);

	/* add a \* to path but don't write more than MAX_PATH */
	if (SCOT_STR_LENGTH (pattern) < MAX_PATH && 
	    pattern [SCOT_STR_LENGTH (pattern)-1] != '\\')
	{
		pattern [SCOT_STR_LENGTH (pattern) + 1] = '\0';
		pattern [SCOT_STR_LENGTH (pattern)] = '\\';
	}

	SCOT_STR_COPY (file->path, pattern);

	if (SCOT_STR_LENGTH (pattern) < MAX_PATH)
	{
		pattern [SCOT_STR_LENGTH (pattern) + 1] = '\0';
		pattern [SCOT_STR_LENGTH (pattern)] = '*';
	}

	// Get the first file
	dir = FindFirstFile(pattern, &(file->file));
	if (dir == INVALID_HANDLE_VALUE)
	{ 
		/* lets hope errno or something is set */
		return NULL;
	}

	SCOT_STRN_COPY (
	      file->path+SCOT_STR_LENGTH (file->path),
	      file->file.cFileName,
	      MAX_PATH-SCOT_STR_LENGTH (file->path));

	return dir;
}


/*
 * This functions retrieves the next file within the given dir.
 *
 * parameters:
 *   dir:  Handle to a directory opened with get_dir_first previously.
 *   path: The path to the directory that is read.
 *         (hmmm, this seems not that ideal to me...why should this
 *          function construct the full path to the found file.
 *          The filename is more that enough i think, as the caller knows
 *          the path already.)
 *   file: A pointer to a structure that holds further information to the
 *         found file. (e.g. the path to the file)
 *   fsym: this has actually no meaning on win32 systems.
 *
 * returns:
 *   This function returns always one of the following:
 *   GET_DIRENT_ERR: if an error occured...errno might or might not be set.
 *   NO_FILES_LEFT:  if the last entry of the directory was read.
 *   GET_DIRENT_OK:  if the next directory entry was read successfully.
 */
int
get_dir_next (DIR_HANDLE dir, const char * path, FILE_DATA * file, int fsym)
{
	if (SCOT_STR_LENGTH (file->path) < MAX_PATH && 
	    file->path [SCOT_STR_LENGTH (file->path)-1] != '\\')
	{
		file->path [SCOT_STR_LENGTH (file->path) + 1] = '\0';
		file->path [SCOT_STR_LENGTH (file->path)] = '\\';
	}

	if (! FindNextFile(dir, &(file->file)))
	{
		if (GetLastError() == ERROR_NO_MORE_FILES)
		{
			return NO_FILES_LEFT;
		}

		return GET_DIRENT_ERR;
	}

	SCOT_STRN_COPY (
	      file->path+SCOT_STR_LENGTH (file->path),
	      file->file.cFileName,
	      MAX_PATH-SCOT_STR_LENGTH (file->path));

	return GET_DIRENT_OK;
}