Commit | Line | Data |
76e3520e |
1 | /* |
2 | |
3 | ipdir.c |
4 | Interface for perl directory functions |
5 | |
6 | */ |
7 | |
8 | #include <ipdir.h> |
9 | |
10 | class CPerlDir : public IPerlDir |
11 | { |
12 | public: |
13 | CPerlDir() { pPerl = NULL; }; |
14 | virtual int MKdir(const char *dirname, int mode, int &err); |
15 | virtual int Chdir(const char *dirname, int &err); |
16 | virtual int Rmdir(const char *dirname, int &err); |
17 | virtual int Close(DIR *dirp, int &err); |
18 | virtual DIR *Open(char *filename, int &err); |
19 | virtual struct direct *Read(DIR *dirp, int &err); |
20 | virtual void Rewind(DIR *dirp, int &err); |
21 | virtual void Seek(DIR *dirp, long loc, int &err); |
22 | virtual long Tell(DIR *dirp, int &err); |
23 | |
24 | inline void SetPerlObj(CPerlObj *p) { pPerl = p; }; |
25 | protected: |
26 | CPerlObj *pPerl; |
27 | }; |
28 | |
29 | int CPerlDir::MKdir(const char *dirname, int mode, int &err) |
30 | { |
31 | return mkdir(dirname); /* just ignore mode */ |
32 | } |
33 | |
34 | int CPerlDir::Chdir(const char *dirname, int &err) |
35 | { |
36 | return chdir(dirname); |
37 | } |
38 | |
39 | int CPerlDir::Rmdir(const char *dirname, int &err) |
40 | { |
41 | return rmdir(dirname); |
42 | } |
43 | |
44 | #define PATHLEN 1024 |
45 | // The idea here is to read all the directory names into a string table |
46 | // (separated by nulls) and when one of the other dir functions is called |
47 | // return the pointer to the current file name. |
48 | DIR *CPerlDir::Open(char *filename, int &err) |
49 | { |
50 | DIR *p; |
51 | long len; |
52 | long idx; |
53 | char scannamespc[PATHLEN]; |
54 | char *scanname = scannamespc; |
55 | struct stat sbuf; |
56 | WIN32_FIND_DATA FindData; |
57 | HANDLE fh; |
58 | |
59 | // Create the search pattern |
60 | strcpy(scanname, filename); |
61 | |
62 | len = strlen(scanname); |
63 | if(len > 1 && ((scanname[len-1] == '/') || (scanname[len-1] == '\\'))) |
64 | { |
65 | // allow directory names of 'x:\' to pass |
66 | if(!(len == 3 && scanname[1] == ':')) |
67 | scanname[len-1] = '\0'; |
68 | } |
69 | |
70 | // check to see if filename is a directory |
71 | if(stat(scanname, &sbuf) < 0 || sbuf.st_mode & _S_IFDIR == 0) |
72 | { |
73 | DWORD dTemp = GetFileAttributes(scanname); |
74 | if(dTemp == 0xffffffff || !(dTemp & FILE_ATTRIBUTE_DIRECTORY)) |
75 | { |
76 | return NULL; |
77 | } |
78 | } |
79 | |
80 | if((scanname[len-1] == '/') || (scanname[len-1] == '\\')) |
81 | scanname[len-1] = '\0'; |
82 | |
83 | strcat(scanname, "/*"); |
84 | |
85 | // Get a DIR structure |
86 | Newz(1501, p, 1, DIR); |
87 | if(p == NULL) |
88 | return NULL; |
89 | |
90 | // do the FindFirstFile call |
91 | fh = FindFirstFile(scanname, &FindData); |
92 | if(fh == INVALID_HANDLE_VALUE) |
93 | { |
94 | Safefree(p); |
95 | return NULL; |
96 | } |
97 | |
98 | // now allocate the first part of the string table for the filenames that we find. |
99 | idx = strlen(FindData.cFileName)+1; |
100 | New(1502, p->start, idx, char); |
101 | if(p->start == NULL) |
102 | { |
103 | FindClose(fh); |
104 | croak("opendir: malloc failed!\n"); |
105 | } |
106 | strcpy(p->start, FindData.cFileName); |
107 | p->nfiles++; |
108 | |
109 | // loop finding all the files that match the wildcard |
110 | // (which should be all of them in this directory!). |
111 | // the variable idx should point one past the null terminator |
112 | // of the previous string found. |
113 | // |
114 | while(FindNextFile(fh, &FindData)) |
115 | { |
116 | len = strlen(FindData.cFileName); |
117 | // bump the string table size by enough for the |
118 | // new name and it's null terminator |
119 | Renew(p->start, idx+len+1, char); |
120 | if(p->start == NULL) |
121 | { |
122 | FindClose(fh); |
123 | croak("opendir: malloc failed!\n"); |
124 | } |
125 | strcpy(&p->start[idx], FindData.cFileName); |
126 | p->nfiles++; |
127 | idx += len+1; |
128 | } |
129 | FindClose(fh); |
130 | p->size = idx; |
131 | p->curr = p->start; |
132 | return p; |
133 | } |
134 | |
135 | int CPerlDir::Close(DIR *dirp, int &err) |
136 | { |
137 | Safefree(dirp->start); |
138 | Safefree(dirp); |
139 | return 1; |
140 | } |
141 | |
142 | // Readdir just returns the current string pointer and bumps the |
143 | // string pointer to the next entry. |
144 | struct direct *CPerlDir::Read(DIR *dirp, int &err) |
145 | { |
146 | int len; |
147 | static int dummy = 0; |
148 | |
149 | if(dirp->curr) |
150 | { // first set up the structure to return |
151 | len = strlen(dirp->curr); |
152 | strcpy(dirp->dirstr.d_name, dirp->curr); |
153 | dirp->dirstr.d_namlen = len; |
154 | |
155 | // Fake an inode |
156 | dirp->dirstr.d_ino = dummy++; |
157 | |
158 | // Now set up for the next call to readdir |
159 | dirp->curr += len + 1; |
160 | if(dirp->curr >= (dirp->start + dirp->size)) |
161 | { |
162 | dirp->curr = NULL; |
163 | } |
164 | |
165 | return &(dirp->dirstr); |
166 | } |
167 | else |
168 | return NULL; |
169 | } |
170 | |
171 | void CPerlDir::Rewind(DIR *dirp, int &err) |
172 | { |
173 | dirp->curr = dirp->start; |
174 | } |
175 | |
176 | void CPerlDir::Seek(DIR *dirp, long loc, int &err) |
177 | { |
178 | dirp->curr = (char *)loc; |
179 | } |
180 | |
181 | long CPerlDir::Tell(DIR *dirp, int &err) |
182 | { |
183 | return (long) dirp->curr; |
184 | } |
185 | |
186 | |