1 /*****************************************************************************/
2 /*                                                                           */
3 /*                 (C) Copyright 1995-1996  Alberto Pasquale                 */
4 /*                 Portions (C) Copyright 1999 Per Lundberg                  */
5 /*                                                                           */
6 /*                   A L L   R I G H T S   R E S E R V E D                   */
7 /*                                                                           */
8 /*****************************************************************************/
9 /*                                                                           */
10 /*   How to contact the author:  Alberto Pasquale of 2:332/504@fidonet       */
11 /*                               Viale Verdi 106                             */
12 /*                               41100 Modena                                */
13 /*                               Italy                                       */
14 /*                                                                           */
15 /*****************************************************************************/
16 
17 #include <stdlib.h>
18 #include <string.h>
19 #include <dirent.h>
20 #include "apgenlib.hpp"
21 
22 #ifdef __QNXNTO__
23    #include <strings.h>
24 #endif // __QNXNTO__
25 
26 typedef _dir *DIRP;
27 
28 #define RAWSIZE 2048
29 
30 typedef int (*QSF) (const void *, const void *);
31 
32 
33 struct _dirblk {
34     byte raw[RAWSIZE];
35     byte *np;   // pointer to next entry
36     _dirblk *next;
37 };
38 
39 
fnameCmp(DIRP * d1,DIRP * d2)40 static int fnameCmp (DIRP *d1, DIRP *d2)
41 {
42     return stricmp ((*d1)->fname, (*d2)->fname);
43 }
44 
45 
46         // private
47 
48 
Add(const FLFFIND * f)49 void DIRcl::Add (const FLFFIND *f)
50 {
51     int namelen = strlen (f->name);
52     int reclen = sizeof (_dir) + namelen;
53 
54     if ((curblk->np - curblk->raw) + reclen + 1 > RAWSIZE) {    // new block
55         curblk = curblk->next = new _dirblk;
56         curblk->np = curblk->raw;
57         curblk->next = NULL;
58     }
59 
60     DIRP dp = (DIRP) curblk->np;
61     dp->namelen = (byte) namelen;
62     dp->Got = FALSE;
63     dp->fsize = f->size;
64     dp->cdate = dosdatimetounix (f->cr_date, f->cr_time);
65     dp->mdate = dosdatimetounix (f->wr_date, f->wr_time);
66     strcpy (dp->fname, f->name);
67 
68     ntot ++;
69     curblk->np += reclen;
70     *curblk->np = 0;
71 }
72 
73 
Read(const char * path)74 void DIRcl::Read (const char *path)
75 {
76     struct dirent *dirent;
77     DIR *dir;
78     FLFFIND ffblk;
79     BOOL done = 0;
80 
81     dir = opendir (path);
82 //the following line seems to be useless
83 //    if (dirent == NULL) done = 1;
84     while (!done)
85       {
86          dirent = readdir (dir);
87          if (dirent == NULL)
88            done = 1;
89          else
90            {
91               strcpy (ffblk.name, dirent->d_name);
92               Add (&ffblk);
93            }
94     }
95 
96     if (ntot == 0)
97         return;
98 
99     dirp = new DIRP[ntot];
100 
101     curblk = dirblkhead;            // build table of pointers
102     byte *np = curblk->raw;
103     for (uint i = 0; i < ntot; i++) {
104         if (*np == 0) {
105             curblk = curblk->next;
106             np = curblk->raw;
107         }
108         dirp[i] = (DIRP) np;
109         np += *np + sizeof (_dir);
110     }
111 
112     qsort (dirp, ntot, sizeof (DIRP), (QSF) fnameCmp);  // and sort
113 }
114 
115 
116                     // public
117 
DIRcl(const char * path)118 DIRcl::DIRcl (const char *path)
119 {
120     curblk = dirblkhead = new _dirblk;
121     curblk->np = curblk->raw;
122     *curblk->np = 0;        // mark end of block
123     curblk->next = NULL;
124 
125     dirp = NULL;
126     ntot = 0;
127 
128     Read (path);
129 }
130 
131 
~DIRcl(void)132 DIRcl::~DIRcl (void)
133 {
134     _dirblk *next;
135     _dirblk *db = dirblkhead;
136     while (db) {
137         next = db->next;
138         delete db;
139         db = next;
140     }
141 
142     if (dirp)
143         delete[] dirp;
144 }
145 
146 
147 
Get(int first)148 _dir *DIRcl::Get (int first)
149 {
150     static uint i;
151 
152     if (first)
153         i = 0;
154 
155     if (i >= ntot)
156         return NULL;
157 
158     return dirp[i++];
159 }
160 
161 
bsf(char * keyname,DIRP * dp)162 static int bsf (char *keyname, DIRP *dp)
163 {
164     return stricmp (keyname, (*dp)->fname);
165 }
166 
167 
Get(const char * filename,BOOL NoDupes)168 _dir *DIRcl::Get (const char *filename, BOOL NoDupes)
169 {
170     if (ntot == 0)
171         return NULL;
172 
173     DIRP *p = (DIRP *) bsearch (filename, dirp, ntot, sizeof (DIRP), (QSF) bsf);
174     if (!p)
175         return NULL;
176 
177     if (NoDupes && (*p)->Got)      // already got
178         return NULL;
179 
180     (*p)->Got = TRUE;
181 
182     return *p;
183 }
184