get directory listing - c

Started by
10 comments, last by godecho 18 years, 4 months ago
I need to get a list of files in a directory, and i remember using some c functions that work on both windows and unix. stuff related to chdir and getcwd or something. Any one know what the function names are?
Advertisement
Directory Control Routines
well i mean for getting a list of files from a directory
hm, it's under "system calls", which is rather stupid.
E8 17 00 42 CE DC D2 DC E4 EA C4 40 CA DA C2 D8 CC 40 CA D0 E8 40E0 CA CA 96 5B B0 16 50 D7 D4 02 B2 02 86 E2 CD 21 58 48 79 F2 C3
The _find* functions are not available on UNIX, so they don't quite meet supagu's requirements. He may be thinking of opendir, readdir et al, but they aren't available on Windows.

Reading directories is platform specific, in large part because of the differences in and complexities of filesystems. Sorry, your recollection may be wrong.
the opendir(etc) and findfirst(etc) arent too different

i _think_ it wouldn't be too hard to write your own wrapper around them, it probably already has been done

EDIT: i hate when typos completly change the meaning of your post...
ah yeah! thats the ones, i damn i thought they worked on *nix, oh well
Quote:Original post by Oluseyi
He may be thinking of opendir, readdir et al, but they aren't available on Windows.

i dont know anything about msvc, but mingw (gcc for windows) does provide opendir and readdir

Dolphins - The sharks of the sea.
Oops, overlooked the Unix requirement. In that case, you can do the following: emulate opendir() on Win32 and use POSIX interfaces in your code (this is nicer than a wrapper because people won't have to learn a new interface). Code to do so follows (200 lines; GPL license; some stuff will have to be stripped for it to compile since there are dependencies):

// opendir/readdir/closedir//// note: we avoid opening directories or returning entries that have// hidden or system attributes set. this is to prevent returning something// like "\System Volume Information", which raises an error upon opening.// 0-initialized by wdir_alloc for safety; this is required for// num_entries_scanned.struct WDIR{	HANDLE hFind;	// the dirent returned by readdir.	// note: having only one global instance is not possible because	// multiple independent opendir/readdir sequences must be supported.	struct dirent ent;	WIN32_FIND_DATA fd;	// since opendir calls FindFirstFile, we need a means of telling the	// first call to readdir that we already have a file.	// that's the case iff this is == 0; we use a counter rather than a	// flag because that allows keeping statistics.	int num_entries_scanned;};// suballocator - satisfies most requests with a reusable static instance.// this avoids hundreds of alloc/free which would fragment the heap.// to guarantee thread-safety, we fall back to malloc if the instance is// already in use. (it's important to avoid suprises since this is such a// low-level routine).static WDIR global_wdir;static uintptr_t global_wdir_is_in_use;// zero-initializes the WDIR (code below relies on this)static inline WDIR* wdir_alloc(){	WDIR* d;	// successfully reserved the global instance	if(CAS(&global_wdir_is_in_use, 0, 1))	{		d = &global_wdir;		memset(d, 0, sizeof(*d));	}	else		d = (WDIR*)calloc(1, sizeof(WDIR));	return d;}static inline void wdir_free(WDIR* d){	if(d == &global_wdir)		global_wdir_is_in_use = 0;	else		free(d);}static const DWORD hs = FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM;// make sure path exists and is a normal (according to attributes) directory.static bool is_normal_dir(const char* path){	const DWORD fa = GetFileAttributes(path);	// .. path not found	if(fa == INVALID_FILE_ATTRIBUTES)		return false;	// .. not a directory	if((fa & FILE_ATTRIBUTE_DIRECTORY) == 0)		return false;	// .. hidden or system attribute(s) set	//    this check is now disabled because wdetect's add_oal_dlls_in_dir	//    needs to open the Windows system directory, which sometimes has	//    these attributes set.	//if((fa & hs) != 0)	//	return false;	return true;}DIR* opendir(const char* path){	if(!is_normal_dir(path))	{		errno = ENOENT;fail:		debug_warn("opendir failed");		return 0;	}	WDIR* d = wdir_alloc();	if(!d)	{		errno = ENOMEM;		goto fail;	}	// build search path for FindFirstFile. note: "path\\dir" only returns	// information about that directory; trailing slashes aren't allowed.	// for dir entries to be returned, we have to append "\\*".	char search_path[PATH_MAX];	snprintf(search_path, ARRAY_SIZE(search_path), "%s\\*", path);	// note: we could store search_path and defer FindFirstFile until	// readdir. this way is a bit more complex but required for	// correctness (we must return a valid DIR iff <path> is valid).	d->hFind = FindFirstFileA(search_path, &d->fd);	if(d->hFind == INVALID_HANDLE_VALUE)	{		// not an error - the directory is just empty.		if(GetLastError() == ERROR_NO_MORE_FILES)			goto success;		// translate Win32 error to errno.		LibError err = LibError_from_win32(0);		LibError_set_errno(err);		// release the WDIR allocated above.		// unfortunately there's no way around this; we need to allocate		// d before FindFirstFile because it uses d->fd. copying from a		// temporary isn't nice either (this free doesn't happen often)		wdir_free(d);		goto fail;	}success:	return d;}struct dirent* readdir(DIR* d_){	WDIR* const d = (WDIR*)d_;	// avoid polluting the last error.	DWORD prev_err = GetLastError();	// first call - skip FindNextFile (see opendir).	if(d->num_entries_scanned == 0)	{		// this directory is empty.		if(d->hFind == INVALID_HANDLE_VALUE)			return 0;		goto already_have_file;	}	// until end of directory or a valid entry was found:	for(;;)	{		if(!FindNextFileA(d->hFind, &d->fd))			goto fail;already_have_file:		d->num_entries_scanned++;		// not a hidden or system entry -> it's valid.		if((d->fd.dwFileAttributes & hs) == 0)			break;	}	// this entry has passed all checks; return information about it.	// (note: d_name is a pointer; see struct dirent definition)	d->ent.d_name = d->fd.cFileName;	return &d->ent;fail:	// FindNextFile failed; determine why and bail.	// .. legit, end of dir reached. don't pollute last error code.	if(GetLastError() == ERROR_NO_MORE_FILES)		SetLastError(prev_err);	else		debug_warn("readdir: FindNextFile failed");	return 0;}// return status for the dirent returned by the last successful// readdir call from the given directory stream.// currently sets st_size, st_mode, and st_mtime; the rest are zeroed.// non-portable, but considerably faster than stat(). used by file_enum.int readdir_stat_np(DIR* d_, struct stat* s){	WDIR* d = (WDIR*)d_;	memset(s, 0, sizeof(struct stat));	s->st_size  = (off_t)u64_from_u32(d->fd.nFileSizeHigh, d->fd.nFileSizeLow);	s->st_mode  = (d->fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)? S_IFDIR : S_IFREG;	s->st_mtime = filetime_to_time_t(&d->fd.ftLastWriteTime);	return 0;}int closedir(DIR* d_){	WDIR* const d = (WDIR*)d_;	FindClose(d->hFind);	wdir_free(d);	return 0;}
E8 17 00 42 CE DC D2 DC E4 EA C4 40 CA DA C2 D8 CC 40 CA D0 E8 40E0 CA CA 96 5B B0 16 50 D7 D4 02 B2 02 86 E2 CD 21 58 48 79 F2 C3
Obligatory link to a boost library [Boost Filesystem Library]

This topic is closed to new replies.

Advertisement