1 /*
2     TiMidity++ -- MIDI to WAVE converter and player
3     Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
4     Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 
20     readdir.c
21 */
22 
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif /* HAVE_CONFIG_H */
26 
27 #ifdef HAVE_STDLIB_H
28 #include <stdlib.h>
29 #else
30 #ifdef HAVE_MALLOC_H
31 #include <malloc.h>
32 #endif
33 #endif
34 
35 #ifndef NO_STRING_H
36 #include <string.h>
37 #else
38 #include <strings.h>
39 #endif
40 
41 #include "timidity.h"
42 #include "common.h"
43 
44 #ifdef __W32__
45 #include "readdir.h"
46 
47 /**********************************************************************
48  * Implement dirent-style opendir/readdir/closedir on Window 95/NT
49  *
50  * Functions defined are opendir(), readdir() and closedir() with the
51  * same prototypes as the normal dirent.h implementation.
52  *
53  * Does not implement telldir(), seekdir(), rewinddir() or scandir().
54  * The dirent struct is compatible with Unix, except that d_ino is
55  * always 1 and d_off is made up as we go along.
56  *
57  * The DIR typedef is not compatible with Unix.
58  **********************************************************************/
59 
opendir(const char * dir)60 API_EXPORT(DIR *) opendir(const char *dir)
61 {
62     DIR *dp;
63     char *filespec;
64     long handle;
65     int index;
66 
67     filespec = safe_malloc(strlen(dir) + 2 + 1);
68     strcpy(filespec, dir);
69     index = strlen(filespec) - 1;
70     if (index >= 0 && (filespec[index] == '/' || filespec[index] == '\\'))
71         filespec[index] = '\0';
72     strcat(filespec, "/*");
73 
74     dp = (DIR *)safe_malloc(sizeof(DIR));
75     dp->offset = 0;
76     dp->finished = 0;
77     dp->dir = safe_strdup(dir);
78 
79     if ((handle = _findfirst(filespec, &(dp->fileinfo))) < 0) {
80         if (errno == ENOENT)
81             dp->finished = 1;
82         else
83         return NULL;
84     }
85 
86     dp->handle = handle;
87     free(filespec);
88 
89     return dp;
90 }
91 
readdir(DIR * dp)92 API_EXPORT(struct dirent *) readdir(DIR *dp)
93 {
94     if (!dp || dp->finished) return NULL;
95 
96     if (dp->offset != 0) {
97         if (_findnext(dp->handle, &(dp->fileinfo)) < 0) {
98             dp->finished = 1;
99             return NULL;
100         }
101     }
102     dp->offset++;
103 
104 #ifdef __BORLANDC__
105 /* Borland C++ */
106     strncpy(dp->dent.d_name, dp->fileinfo.ff_name, _MAX_FNAME);
107 #else
108     strncpy(dp->dent.d_name, dp->fileinfo.name, _MAX_FNAME);
109 #endif /* __BORLANDC__ */
110 
111     dp->dent.d_name[_MAX_FNAME] = '\0';
112     dp->dent.d_ino = 1;
113     dp->dent.d_reclen = strlen(dp->dent.d_name);
114     dp->dent.d_off = dp->offset;
115 
116     return &(dp->dent);
117 }
118 
closedir(DIR * dp)119 API_EXPORT(int) closedir(DIR *dp)
120 {
121     if (!dp) return 0;
122 
123 #ifndef __BORLANDC__
124     _findclose(dp->handle);
125 #endif
126     if (dp->dir) free(dp->dir);
127     if (dp) free(dp);
128 
129     return 0;
130 }
131 #endif /* __W32__ */
132