xref: /openbsd/gnu/usr.bin/cvs/os2/dirent.c (revision 3cab2bb3)
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 
31 DIR *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 
132 struct 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 
141 long telldir(DIR *dirp)
142 {
143     return((long) dirp->cur_ent);
144 }
145 
146 
147 void seekdir(DIR *dirp, long loc)
148 {
149     dirp->cur_ent = (int) loc;
150     return;
151 }
152 
153 
154 void rewinddir(DIR *dirp)
155 {
156     dirp->cur_ent = 0;
157     return;
158 }
159 
160 
161 void 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