1/*  msd_dir.c - portable directory routines
2    Copyright (C) 1990 by Thorsten Ohl, td12@ddagsi3.bitnet
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 1, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.  */
13
14/* Everything non trivial in this code is from: @(#)msd_dir.c 1.4
15   87/11/06.  A public domain implementation of BSD directory routines
16   for MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
17   August 1897 */
18
19
20#include <io.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26
27#include <dos.h>
28
29#include <ndir.h>
30
31static void free_dircontents (struct _dircontents *);
32
33/* find ALL files! */
34#define ATTRIBUTES	(_A_RDONLY | _A_HIDDEN | _A_SYSTEM | _A_SUBDIR)
35
36
37
38DIR *
39opendir (const char *name)
40{
41  struct _finddata_t find_buf;
42  DIR *dirp;
43  struct _dircontents *dp;
44  char name_buf[_MAX_PATH + 1];
45  char *slash = "";
46  long hFile;
47
48  if (!name)
49    name = "";
50  else if (*name)
51    {
52      const char *s;
53      int l = strlen (name);
54
55      s = name + l - 1;
56      if ( !(l == 2 && *s == ':') && *s != '\\' && *s != '/')
57	slash = "/";	/* save to insert slash between path and "*.*" */
58    }
59
60  strcat (strcat (strcpy (name_buf, name), slash), "*.*");
61
62  dirp = (DIR *) malloc (sizeof (DIR));
63  if (dirp == (DIR *)0)
64    return (DIR *)0;
65
66  dirp->dd_loc = 0;
67  dirp->dd_contents = dirp->dd_cp = (struct _dircontents *) 0;
68
69  if ((hFile = _findfirst (name_buf, &find_buf)) < 0)
70    {
71      free (dirp);
72      return (DIR *)0;
73    }
74
75  do
76    {
77      dp = (struct _dircontents *) malloc (sizeof (struct _dircontents));
78      if (dp == (struct _dircontents *)0)
79	{
80	  free_dircontents (dirp->dd_contents);
81	  return (DIR *)0;
82	}
83
84      dp->_d_entry = malloc (strlen (find_buf.name) + 1);
85      if (dp->_d_entry == (char *)0)
86	{
87	  free (dp);
88	  free_dircontents (dirp->dd_contents);
89	  return (DIR *)0;
90	}
91
92      if (dirp->dd_contents)
93	dirp->dd_cp = dirp->dd_cp->_d_next = dp;
94      else
95	dirp->dd_contents = dirp->dd_cp = dp;
96
97      strcpy (dp->_d_entry, find_buf.name);
98
99      dp->_d_next = (struct _dircontents *)0;
100
101    } while (!_findnext (hFile, &find_buf));
102
103  dirp->dd_cp = dirp->dd_contents;
104
105  _findclose(hFile);
106
107  return dirp;
108}
109
110
111void
112closedir (DIR *dirp)
113{
114  free_dircontents (dirp->dd_contents);
115  free ((char *) dirp);
116}
117
118
119struct direct *
120readdir (DIR *dirp)
121{
122  static struct direct dp;
123
124  if (dirp->dd_cp == (struct _dircontents *)0)
125    return (struct direct *)0;
126  dp.d_namlen = dp.d_reclen =
127    strlen (strcpy (dp.d_name, dirp->dd_cp->_d_entry));
128#if 0 /* JB */
129  strlwr (dp.d_name);		/* JF */
130#endif
131  dp.d_ino = 0;
132  dirp->dd_cp = dirp->dd_cp->_d_next;
133  dirp->dd_loc++;
134
135  return &dp;
136}
137
138
139void
140seekdir (DIR *dirp, long off)
141{
142  long i = off;
143  struct _dircontents *dp;
144
145  if (off < 0)
146    return;
147  for (dp = dirp->dd_contents; --i >= 0 && dp; dp = dp->_d_next)
148    ;
149  dirp->dd_loc = off - (i + 1);
150  dirp->dd_cp = dp;
151}
152
153
154long
155telldir (DIR *dirp)
156{
157  return dirp->dd_loc;
158}
159
160
161/* Garbage collection */
162
163static void
164free_dircontents (struct _dircontents *dp)
165{
166  struct _dircontents *odp;
167
168  while (dp)
169    {
170      if (dp->_d_entry)
171	free (dp->_d_entry);
172      dp = (odp = dp)->_d_next;
173      free (odp);
174    }
175}
176
177
178#ifdef TEST
179
180void main (int argc, char *argv[]);
181
182void
183main (int argc, char *argv[])
184{
185  static DIR *directory;
186  struct direct *entry = (struct direct *)0;
187
188  char *name = "";
189
190  if (argc > 1)
191    name = argv[1];
192
193  directory = opendir (name);
194
195  if (!directory)
196    {
197      fprintf (stderr, "can't open directory `%s'.\n", name);
198      exit (2);
199    }
200
201  while (entry = readdir (directory))
202    printf ("> %s\n", entry->d_name);
203
204  printf ("done.\n");
205}
206
207#endif /* TEST */
208
209/*
210 * Local Variables:
211 * mode:C
212 * ChangeLog:ChangeLog
213 * compile-command:make
214 * End:
215 */
216