15 #define INCL_DOSFILEMGR
16 #define INCL_DOSERRORS
20 # define FFBUF FILEFINDBUF3
23 * LS20 recommends a request count of 100, but according to the
24 * APAR text it does not lead to missing files, just to funny
25 * numbers of returned entries.
27 * LS30 HPFS386 requires a count greater than 2, or some files
28 * are missing (those starting with a character less that '.').
30 * Novell looses entries which overflow the buffer. In previous
31 * versions of dirent2, this could have lead to missing files
32 * when the average length of 100 directory entries was 40 bytes
33 * or more (quite unlikely for files on a Novell server).
35 * Conclusion: Make sure that the entries all fit into the buffer
36 * and that the buffer is large enough for more than 2 entries
37 * (each entry is at most 300 bytes long). And ignore the LS20
41 # define BufSz (25 * (sizeof(FILEFINDBUF3)+1))
43 # define FFBUF FILEFINDBUF
49 #if defined(__IBMC__) || defined(__IBMCPP__)
50 #define error(rc) _doserrno = rc, errno = EOS2ERR
51 #elif defined(MICROSOFT)
52 #define error(rc) _doserrno = rc, errno = 255
54 #define error(rc) errno = 255
58 HDIR handle
; /* DosFindFirst handle */
59 char fstype
; /* filesystem type */
60 Word count
; /* valid entries in <ffbuf> */
61 long number
; /* absolute number of next entry */
62 int index
; /* relative number of next entry */
63 FFBUF
* next
; /* pointer to next entry */
64 char name
[MAXPATHLEN
+3]; /* directory name */
65 unsigned attrmask
; /* attribute mask for seekdir */
66 struct dirent entry
; /* buffer for directory entry */
71 * Return first char of filesystem type, or 0 if unknown.
74 getFSType(const char *path
)
76 static char cache
[1+26];
77 char drive
[3], info
[512];
81 if (isalpha(path
[0]) && path
[1] == ':') {
82 unit
= toupper(path
[0]) - '@';
87 if (DosQueryCurrentDisk(&unit
, &driveMap
))
89 if (DosQCurDisk(&unit
, &driveMap
))
94 if ((path
[0] == '\\' || path
[0] == '/')
95 && (path
[1] == '\\' || path
[1] == '/'))
101 drive
[0] = '@' + unit
;
104 infolen
= sizeof info
;
106 if (DosQueryFSAttach(drive
, 0, FSAIL_QUERYNAME
, (PVOID
)info
, &infolen
))
108 if (infolen
>= sizeof(FSQBUFFER2
)) {
109 FSQBUFFER2
*p
= (FSQBUFFER2
*)info
;
110 r
= p
->szFSDName
[p
->cbName
];
113 if (DosQFSAttach((PSZ
)drive
, 0, FSAIL_QUERYNAME
, (PVOID
)info
, &infolen
, 0))
116 char *p
= info
+ sizeof(USHORT
);
117 p
+= sizeof(USHORT
) + *(USHORT
*)p
+ 1 + sizeof(USHORT
);
122 return cache
[unit
] = r
;
126 abs_path(const char *name
, char *buffer
, int len
)
129 if (isalpha(name
[0]) && name
[1] == ':' && name
[2] == '\0') {
137 if (DosQueryPathInfo((PSZ
)name
, FIL_QUERYFULLNAME
, buffer
, len
))
139 if (DosQPathInfo((PSZ
)name
, FIL_QUERYFULLNAME
, (PBYTE
)buffer
, len
, 0L))
146 openxdir(const char *path
, unsigned att_mask
)
149 char name
[MAXPATHLEN
+3];
152 dir
= malloc(sizeof(DIR));
158 strncpy(name
, path
, MAXPATHLEN
);
159 name
[MAXPATHLEN
] = '\0';
160 switch (name
[strlen(name
)-1]) {
169 if (!abs_path(name
, dir
->name
, MAXPATHLEN
+1))
170 strcpy(dir
->name
, name
);
171 if (dir
->name
[strlen(dir
->name
)-1] == '\\')
172 strcat(dir
->name
, "*");
174 strcat(dir
->name
, "\\*");
176 dir
->fstype
= getFSType(dir
->name
);
177 dir
->attrmask
= att_mask
| A_DIR
;
179 dir
->handle
= HDIR_CREATE
;
182 rc
= DosFindFirst(dir
->name
, &dir
->handle
, dir
->attrmask
,
183 dir
->ffbuf
, sizeof dir
->ffbuf
, &dir
->count
, FIL_STANDARD
);
185 rc
= DosFindFirst((PSZ
)dir
->name
, &dir
->handle
, dir
->attrmask
,
186 (PFILEFINDBUF
)dir
->ffbuf
, sizeof dir
->ffbuf
, &dir
->count
, 0);
194 case ERROR_NO_MORE_FILES
:
200 dir
->next
= (FFBUF
*)dir
->ffbuf
;
206 opendir(const char *pathname
)
208 return openxdir(pathname
, 0);
214 static int dummy_ino
= 2;
216 if (dir
->index
== dir
->count
) {
220 rc
= DosFindNext(dir
->handle
, dir
->ffbuf
,
221 sizeof dir
->ffbuf
, &dir
->count
);
223 rc
= DosFindNext(dir
->handle
, (PFILEFINDBUF
)dir
->ffbuf
,
224 sizeof dir
->ffbuf
, &dir
->count
);
232 dir
->next
= (FFBUF
*)dir
->ffbuf
;
235 if (dir
->index
== dir
->count
)
238 memcpy(dir
->entry
.d_name
, dir
->next
->achName
, dir
->next
->cchName
);
239 dir
->entry
.d_name
[dir
->next
->cchName
] = '\0';
240 dir
->entry
.d_ino
= dummy_ino
++;
241 dir
->entry
.d_reclen
= dir
->next
->cchName
;
242 dir
->entry
.d_namlen
= dir
->next
->cchName
;
243 dir
->entry
.d_size
= dir
->next
->cbFile
;
244 dir
->entry
.d_attribute
= dir
->next
->attrFile
;
245 dir
->entry
.d_time
= *(USHORT
*)&dir
->next
->ftimeLastWrite
;
246 dir
->entry
.d_date
= *(USHORT
*)&dir
->next
->fdateLastWrite
;
248 switch (dir
->fstype
) {
251 if (dir
->next
->attrFile
& FILE_DIRECTORY
)
252 strupr(dir
->entry
.d_name
);
254 strlwr(dir
->entry
.d_name
);
258 dir
->next
= (FFBUF
*)((BYTE
*)dir
->next
+ dir
->next
->oNextEntryOffset
);
260 dir
->next
= (FFBUF
*)((BYTE
*)dir
->next
->achName
+ dir
->next
->cchName
+ 1);
275 seekdir(DIR *dir
, long off
)
277 if (dir
->number
> off
) {
278 char name
[MAXPATHLEN
+2];
281 DosFindClose(dir
->handle
);
283 strcpy(name
, dir
->name
);
286 dir
->handle
= HDIR_CREATE
;
289 rc
= DosFindFirst(name
, &dir
->handle
, dir
->attrmask
,
290 dir
->ffbuf
, sizeof dir
->ffbuf
, &dir
->count
, FIL_STANDARD
);
292 rc
= DosFindFirst((PSZ
)name
, &dir
->handle
, dir
->attrmask
,
293 (PFILEFINDBUF
)dir
->ffbuf
, sizeof dir
->ffbuf
, &dir
->count
, 0);
300 case ERROR_NO_MORE_FILES
:
306 dir
->next
= (FFBUF
*)dir
->ffbuf
;
309 while (dir
->number
< off
&& readdir(dir
))
316 DosFindClose(dir
->handle
);
320 /*****************************************************************************/
324 main(int argc
, char **argv
)
330 for (i
= 1; i
< argc
; ++i
) {
331 dir
= opendir(argv
[i
]);
334 while (ep
= readdir(dir
))
335 if (strchr("\\/:", argv
[i
] [strlen(argv
[i
]) - 1]))
336 printf("%s%s\n", argv
[i
], ep
->d_name
);
338 printf("%s/%s\n", argv
[i
], ep
->d_name
);