-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdir-list.c
139 lines (113 loc) · 2.58 KB
/
dir-list.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/* Cross-Platform System Programming Guide: L1: print the current directory contents to console */
#include <assert.h>
#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#define ERR_NOMOREFILES ERROR_NO_MORE_FILES
typedef struct {
HANDLE dir;
WIN32_FIND_DATAW data; // Windows fills this object for us for each file found in the directory
char name[260 * 4]; // UTF-8 buffer large enough to hold 'data.cFileName'
unsigned next;
} dirscan;
int dirscan_open(dirscan *d, const char *path)
{
if (path[0] == '\0') {
SetLastError(ERROR_PATH_NOT_FOUND);
return -1;
}
// Append "\\*" to the directory path
wchar_t w[1000];
int r = MultiByteToWideChar(CP_UTF8, 0, path, -1, w, 1000 - 2);
if (r == 0)
return -1;
r--;
w[r++] = '\\';
w[r++] = '*';
w[r] = '\0';
// open directory and get its first file
HANDLE dir = FindFirstFileW(w, &d->data);
if (dir == INVALID_HANDLE_VALUE && GetLastError() != ERROR_FILE_NOT_FOUND)
return -1;
d->dir = dir;
return 0;
}
void dirscan_close(dirscan *d)
{
FindClose(d->dir);
d->dir = INVALID_HANDLE_VALUE;
}
const char* dirscan_next(dirscan *d)
{
if (!d->next) {
// 1. We already have the info on the first file
if (d->dir == INVALID_HANDLE_VALUE) {
SetLastError(ERROR_NO_MORE_FILES);
return NULL;
}
d->next = 1;
} else {
// 2. Get info on the next file in directory
if (!FindNextFileW(d->dir, &d->data))
return NULL;
}
if (0 == WideCharToMultiByte(CP_UTF8, 0, d->data.cFileName, -1, d->name, sizeof(d->name), NULL, NULL))
return NULL;
return d->name;
}
int err_last()
{
return GetLastError();
}
#else // UNIX:
#include <dirent.h>
#include <errno.h>
#define ERR_NOMOREFILES 0
typedef struct {
DIR *dir;
} dirscan;
/** Open directory listing.
Return 0 on success */
int dirscan_open(dirscan *d, const char *path)
{
DIR *dir = opendir(path);
if (dir == NULL)
return -1;
d->dir = dir;
return 0;
}
/** Close directory listing */
void dirscan_close(dirscan *d)
{
closedir(d->dir);
d->dir = NULL;
}
/** Get name (without path) of the next file in directory.
Return NULL if there are no more files left. */
const char* dirscan_next(dirscan *d)
{
const struct dirent *de;
errno = ERR_NOMOREFILES;
if (NULL == (de = readdir(d->dir)))
return NULL;
return de->d_name;
}
int err_last()
{
return errno;
}
#endif
void main()
{
// open directory listing
dirscan ds = {};
assert(0 == dirscan_open(&ds, "."));
// read file names one by one and print to stdout
const char *name;
while (NULL != (name = dirscan_next(&ds))) {
puts(name);
}
assert(err_last() == ERR_NOMOREFILES);
// close descriptor
dirscan_close(&ds);
}