1/*
2 *              Author:     Bob Withers
3 *              Copyright (c) 1993, All Rights Reserved
4 *
5 *                              NOTICE
6 *
7 * Permission to use, copy, modify, and distribute this software and
8 * its documentation for any purpose and without fee is hereby granted
9 * provided that the above copyright notice appears in all copies and
10 * that both the copyright notice and this permission notice appear in
11 * supporting documentation.
12 *
13 * The author makes no representations about the suitability of this
14 * software for any purpose.  This software is provided ``as is''
15 * without express or implied warranty.
16 */
17
18#include <stdlib.h>
19#include <string.h>
20
21#define INCL_DOSFILEMGR
22#define INCL_DOSERRORS
23#include <os2.h>
24
25#include "dirent.h"
26
27
28#define DIRENT_INCR             25
29
30
31DIR *opendir(char *filename)
32{
33    auto     size_t             len;
34    auto     DIR               *dirp;
35    auto     char              *p;
36    auto     HDIR               hdir;
37
38#ifdef OS2_16
39    auto     USHORT             rc;         /* for 16 bit OS/2          */
40    auto     FILEFINDBUF        ff;
41    auto     USHORT             cnt;
42#else
43    auto     APIRET             rc;         /* for 32 bit OS/2          */
44    auto     FILEFINDBUF3       ff;
45    auto     ULONG              cnt;
46#endif  /* OS2_16 */
47
48    if (NULL == filename || '\0' == filename[0])
49        filename = ".";
50
51    dirp = malloc(sizeof(*dirp));
52    if (NULL == dirp)
53        return(NULL);
54
55    len = strlen(filename);
56    dirp->dirname = malloc(len + 5);
57    if (NULL == dirp->dirname)
58    {
59        free(dirp);
60        return(NULL);
61    }
62
63    dirp->max_ent = 0;
64    dirp->tot_ent = 0;
65    dirp->cur_ent = 0;
66    dirp->entp    = NULL;
67    strcpy(dirp->dirname, filename);
68    for (p = dirp->dirname; *p; ++p)
69    {
70        if ('/' == *p)
71            *p = '\\';
72    }
73
74    if ('\\' != dirp->dirname[len - 1])
75        strcat(dirp->dirname, "\\");
76
77    strcat(dirp->dirname, "*.*");
78
79    hdir = HDIR_SYSTEM;
80    cnt  = 1;
81    rc = DosFindFirst(dirp->dirname, &hdir,
82                      FILE_NORMAL | FILE_READONLY | FILE_HIDDEN |
83                      FILE_SYSTEM | FILE_DIRECTORY | FILE_ARCHIVED,
84                      &ff, sizeof(ff), &cnt, FIL_STANDARD);
85
86    while (NO_ERROR == rc)
87    {
88        auto     struct dirent     *entp;
89
90        if (dirp->tot_ent >= dirp->max_ent)
91        {
92            auto     struct dirent    **p;
93
94            dirp->max_ent += DIRENT_INCR;
95            p = realloc(dirp->entp, dirp->max_ent * sizeof(entp));
96            if (NULL == p)
97            {
98                rc = ERROR_NOT_ENOUGH_MEMORY;
99                break;
100            }
101
102            dirp->entp = p;
103        }
104
105        entp = malloc(sizeof(*entp) + (size_t) ff.cchName);
106        if (NULL == entp)
107        {
108            rc = ERROR_NOT_ENOUGH_MEMORY;
109            break;
110        }
111
112        entp->d_ino = 0;
113        entp->d_off = dirp->tot_ent;
114        entp->d_namlen = (unsigned short) ff.cchName;
115        memcpy(entp->d_name, ff.achName, entp->d_namlen);
116        entp->d_name[entp->d_namlen] = '\0';
117        dirp->entp[dirp->tot_ent++] = entp;
118
119        cnt = 1;
120        rc = DosFindNext(hdir, &ff, sizeof(ff), &cnt);
121    }
122
123    DosFindClose(hdir);
124    if (ERROR_NO_MORE_FILES == rc)
125        return(dirp);
126
127    closedir(dirp);
128    return(NULL);
129}
130
131
132struct dirent *readdir(DIR *dirp)
133{
134    if (dirp->cur_ent < 0 || dirp->cur_ent >= dirp->tot_ent)
135        return(NULL);
136
137    return(dirp->entp[dirp->cur_ent++]);
138}
139
140
141long telldir(DIR *dirp)
142{
143    return((long) dirp->cur_ent);
144}
145
146
147void seekdir(DIR *dirp, long loc)
148{
149    dirp->cur_ent = (int) loc;
150    return;
151}
152
153
154void rewinddir(DIR *dirp)
155{
156    dirp->cur_ent = 0;
157    return;
158}
159
160
161void closedir(DIR *dirp)
162{
163    if (dirp)
164    {
165        if (dirp->dirname)
166            free(dirp->dirname);
167
168        if (dirp->entp)
169        {
170            register int        i;
171
172            for (i = 0; i < dirp->tot_ent; ++i)
173                free(dirp->entp[i]);
174
175            free(dirp->entp);
176        }
177    }
178
179    return;
180}
181