]> git.gag.com Git - debian/tar/blob - src/msd_dir.c
27414071a1b11d5ab74cfdf529ce20301c315a47
[debian/tar] / src / msd_dir.c
1 /*
2  * @(#)msd_dir.c 1.4 87/11/06   Public Domain.
3  *
4  *  A public domain implementation of BSD directory routines for
5  *  MS-DOS.  Written by Michael Rendell ({uunet,utai}michael@garfield),
6  *  August 1897
7  */
8
9 #include        <sys/types.h>
10 #include        <sys/stat.h>
11 #include        "msd_dir.h"
12 #ifndef __TURBOC__
13 #include        <malloc.h>
14 #else
15 #include        <stdlib.h>
16 #endif
17 #include        <string.h>
18 #include        <dos.h>
19
20 #ifndef NULL
21 # define        NULL    0
22 #endif /* NULL */
23
24 #ifndef MAXPATHLEN
25 # define        MAXPATHLEN      255
26 #endif /* MAXPATHLEN */
27
28 /* attribute stuff */
29 #define A_RONLY         0x01
30 #define A_HIDDEN        0x02
31 #define A_SYSTEM        0x04
32 #define A_LABEL         0x08
33 #define A_DIR           0x10
34 #define A_ARCHIVE       0x20
35
36 /* dos call values */
37 #define DOSI_FINDF      0x4e
38 #define DOSI_FINDN      0x4f
39 #define DOSI_SDTA       0x1a
40
41 #define Newisnull(a, t)         ((a = (t *) malloc(sizeof(t))) == (t *) NULL)
42 /* #define      ATTRIBUTES              (A_DIR | A_HIDDEN | A_SYSTEM) */
43 #define ATTRIBUTES      (A_RONLY | A_SYSTEM | A_DIR)
44
45 /* what find first/next calls look use */
46 typedef struct
47   {
48     char d_buf[21];
49     char d_attribute;
50     unsigned short d_time;
51     unsigned short d_date;
52     long d_size;
53     char d_name[13];
54   }
55
56 Dta_buf;
57
58 static char *getdirent ();
59 static void mysetdta ();
60 static void free_dircontents ();
61
62 static Dta_buf dtabuf;
63 static Dta_buf *dtapnt = &dtabuf;
64 static union REGS reg, nreg;
65
66 #if     defined(M_I86LM)
67 static struct SREGS sreg;
68 #endif
69
70 DIR *
71 opendir (name)
72      char *name;
73 {
74   struct stat statb;
75   DIR *dirp;
76   char c;
77   char *s;
78   struct _dircontents *dp;
79   char nbuf[MAXPATHLEN + 1];
80
81   if (stat (name, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
82     return (DIR *) NULL;
83   if (Newisnull (dirp, DIR))
84     return (DIR *) NULL;
85   if (*name && (c = name[strlen (name) - 1]) != '\\' && c != '/')
86     (void) strcat (strcpy (nbuf, name), "\\*.*");
87   else
88     (void) strcat (strcpy (nbuf, name), "*.*");
89   dirp->dd_loc = 0;
90   mysetdta ();
91   dirp->dd_contents = dirp->dd_cp = (struct _dircontents *) NULL;
92   if ((s = getdirent (nbuf)) == (char *) NULL)
93     return dirp;
94   do
95     {
96       if (Newisnull (dp, struct _dircontents) || (dp->_d_entry =
97                      malloc ((unsigned) (strlen (s) + 1))) == (char *) NULL)
98         {
99           if (dp)
100             free ((char *) dp);
101           free_dircontents (dirp->dd_contents);
102           return (DIR *) NULL;
103         }
104       if (dirp->dd_contents)
105         dirp->dd_cp = dirp->dd_cp->_d_next = dp;
106       else
107         dirp->dd_contents = dirp->dd_cp = dp;
108       (void) strcpy (dp->_d_entry, s);
109       dp->_d_next = (struct _dircontents *) NULL;
110     }
111   while ((s = getdirent ((char *) NULL)) != (char *) NULL);
112   dirp->dd_cp = dirp->dd_contents;
113
114   return dirp;
115 }
116
117 void
118 closedir (dirp)
119      DIR *dirp;
120 {
121   free_dircontents (dirp->dd_contents);
122   free ((char *) dirp);
123 }
124
125 struct dirent *
126 readdir (dirp)
127      DIR *dirp;
128 {
129   static struct dirent dp;
130
131   if (dirp->dd_cp == (struct _dircontents *) NULL)
132     return (struct dirent *) NULL;
133   dp.d_namlen = dp.d_reclen =
134     strlen (strcpy (dp.d_name, dirp->dd_cp->_d_entry));
135   strlwr (dp.d_name);           /* JF */
136   dp.d_ino = 0;
137   dirp->dd_cp = dirp->dd_cp->_d_next;
138   dirp->dd_loc++;
139
140   return &dp;
141 }
142
143 void
144 seekdir (dirp, off)
145      DIR *dirp;
146      long off;
147 {
148   long i = off;
149   struct _dircontents *dp;
150
151   if (off < 0)
152     return;
153   for (dp = dirp->dd_contents; --i >= 0 && dp; dp = dp->_d_next)
154     ;
155   dirp->dd_loc = off - (i + 1);
156   dirp->dd_cp = dp;
157 }
158
159 long
160 telldir (dirp)
161      DIR *dirp;
162 {
163   return dirp->dd_loc;
164 }
165
166 static void
167 free_dircontents (dp)
168      struct _dircontents *dp;
169 {
170   struct _dircontents *odp;
171
172   while (dp)
173     {
174       if (dp->_d_entry)
175         free (dp->_d_entry);
176       dp = (odp = dp)->_d_next;
177       free ((char *) odp);
178     }
179 }
180
181 static char *
182 getdirent (dir)
183      char *dir;
184 {
185   if (dir != (char *) NULL)
186     {                           /* get first entry */
187       reg.h.ah = DOSI_FINDF;
188       reg.h.cl = ATTRIBUTES;
189 #if     defined(M_I86LM)
190       reg.x.dx = FP_OFF (dir);
191       sreg.ds = FP_SEG (dir);
192 #else
193       reg.x.dx = (unsigned) dir;
194 #endif
195     }
196   else
197     {                           /* get next entry */
198       reg.h.ah = DOSI_FINDN;
199 #if     defined(M_I86LM)
200       reg.x.dx = FP_OFF (dtapnt);
201       sreg.ds = FP_SEG (dtapnt);
202 #else
203       reg.x.dx = (unsigned) dtapnt;
204 #endif
205     }
206 #if     defined(M_I86LM)
207   intdosx (&reg, &nreg, &sreg);
208 #else
209   intdos (&reg, &nreg);
210 #endif
211   if (nreg.x.cflag)
212     return (char *) NULL;
213
214   return dtabuf.d_name;
215 }
216
217 static void
218 mysetdta ()
219 {
220   reg.h.ah = DOSI_SDTA;
221 #if     defined(M_I86LM)
222   reg.x.dx = FP_OFF (dtapnt);
223   sreg.ds = FP_SEG (dtapnt);
224   intdosx (&reg, &nreg, &sreg);
225 #else
226   reg.x.dx = (int) dtapnt;
227   intdos (&reg, &nreg);
228 #endif
229 }