source: branches/samba-3.0/examples/libsmbclient/smbwrapper/smbw_dir.c

Last change on this file was 1, checked in by Paul Smedley, 18 years ago

Initial code import

File size: 9.8 KB
Line 
1/*
2 Unix SMB/Netbios implementation.
3 Version 2.0
4 SMB wrapper directory functions
5 Copyright (C) Andrew Tridgell 1998
6 Copyright (C) Derrell Lipman 2003-2005
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21*/
22
23#include "smbw.h"
24#include "bsd-strlfunc.h"
25
26/*****************************************************
27determine if a directory handle is a smb one
28*******************************************************/
29int smbw_dirp(DIR * dirp)
30{
31 return ((char *) dirp >= (char *) smbw_fd_map &&
32 (char *) dirp < (char *) &smbw_fd_map[__FD_SETSIZE] &&
33 *(int *) dirp != -1);
34}
35
36
37/*****************************************************
38a wrapper for getdents()
39*******************************************************/
40int smbw_getdents(unsigned int fd_smbw,
41 struct SMBW_dirent *dirent_external,
42 int count)
43{
44 int remaining;
45 int fd_client = smbw_fd_map[fd_smbw];
46 struct smbc_dirent *dirent_internal;
47
48
49 for (remaining = count;
50 remaining > sizeof(struct SMBW_dirent);
51 dirent_external++) {
52
53 /*
54 * We do these one at a time because there's otherwise no way
55 * to limit how many smbc_getdents() will return for us, and
56 * if it returns too many, it also doesn't give us offsets to
57 * be able to seek back to where we need to be. In practice,
58 * this one-at-a-time retrieval isn't a problem because the
59 * time-consuming network transaction is all done at
60 * smbc_opendir() time.
61 */
62 dirent_internal = smbc_readdir(fd_client);
63 if (dirent_internal == NULL) {
64 break;
65 }
66
67 remaining -= sizeof(struct SMBW_dirent);
68
69 dirent_external->d_ino = -1; /* not supported */
70 dirent_external->d_off = smbc_telldir(fd_client);
71 dirent_external->d_reclen = sizeof(struct SMBW_dirent);
72 dirent_external->d_type = dirent_internal->smbc_type;
73
74 smbw_strlcpy(dirent_external->d_name,
75 dirent_internal->name,
76 sizeof(dirent_external->d_name) - 1);
77 smbw_strlcpy(dirent_external->d_comment,
78 dirent_internal->comment,
79 sizeof(dirent_external->d_comment) - 1);
80 }
81
82 return(count - remaining);
83}
84
85
86/*****************************************************
87a wrapper for chdir()
88*******************************************************/
89int smbw_chdir(const char *name)
90{
91 int simulate;
92 struct stat statbuf;
93 char path[PATH_MAX];
94 char *p;
95
96 SMBW_INIT();
97
98 if (!name) {
99 errno = EINVAL;
100 return -1;
101 }
102
103 if (! smbw_path((char *) name)) {
104 if ((* smbw_libc.chdir)(name) == 0) {
105 *smbw_cwd = '\0';
106 return 0;
107 }
108
109 return -1;
110 }
111
112 smbw_fix_path(name, path);
113
114 /* ensure it exists */
115 p = path + 6; /* look just past smb:// */
116 simulate = (strchr(p, '/') == NULL);
117
118 /* special case for full-network scan, workgroups, and servers */
119 if (! simulate) {
120
121 if (smbc_stat(path, &statbuf) < 0) {
122 return -1;
123 }
124
125 /* ensure it's a directory */
126 if (! S_ISDIR(statbuf.st_mode)) {
127 errno = ENOTDIR;
128 return -1;
129 }
130 }
131
132 smbw_strlcpy(smbw_cwd, path, PATH_MAX);
133
134 /* we don't want the old directory to be busy */
135 (* smbw_libc.chdir)("/");
136
137 return 0;
138}
139
140
141/*****************************************************
142a wrapper for mkdir()
143*******************************************************/
144int smbw_mkdir(const char *fname, mode_t mode)
145{
146 char path[PATH_MAX];
147
148 if (!fname) {
149 errno = EINVAL;
150 return -1;
151 }
152
153 SMBW_INIT();
154
155 smbw_fix_path(fname, path);
156 return smbc_mkdir(path, mode);
157}
158
159/*****************************************************
160a wrapper for rmdir()
161*******************************************************/
162int smbw_rmdir(const char *fname)
163{
164 char path[PATH_MAX];
165
166 if (!fname) {
167 errno = EINVAL;
168 return -1;
169 }
170
171 SMBW_INIT();
172
173 smbw_fix_path(fname, path);
174 return smbc_rmdir(path);
175}
176
177
178/*****************************************************
179a wrapper for getcwd()
180*******************************************************/
181char *smbw_getcwd(char *buf, size_t size)
182{
183 SMBW_INIT();
184
185 if (*smbw_cwd == '\0') {
186 return (* smbw_libc.getcwd)(buf, size);
187 }
188
189 if (buf == NULL) {
190 if (size == 0) {
191 size = strlen(smbw_cwd) + 1;
192 }
193 buf = malloc(size);
194 if (buf == NULL) {
195 errno = ENOMEM;
196 return NULL;
197 }
198 }
199
200 smbw_strlcpy(buf, smbw_cwd, size);
201 buf[size-1] = '\0';
202 return buf;
203}
204
205/*****************************************************
206a wrapper for fchdir()
207*******************************************************/
208int smbw_fchdir(int fd_smbw)
209{
210 int ret;
211
212 SMBW_INIT();
213
214 if (! smbw_fd(fd_smbw)) {
215 ret = (* smbw_libc.fchdir)(fd_smbw);
216 (void) (* smbw_libc.getcwd)(smbw_cwd, PATH_MAX);
217 return ret;
218 }
219
220 errno = EACCES;
221 return -1;
222}
223
224/*****************************************************
225open a directory on the server
226*******************************************************/
227DIR *smbw_opendir(const char *fname)
228{
229 int fd_client;
230 int fd_smbw;
231 char path[PATH_MAX];
232 DIR * dirp;
233
234 SMBW_INIT();
235
236 if (!fname) {
237 errno = EINVAL;
238 return NULL;
239 }
240
241 fd_smbw = (smbw_libc.open)(SMBW_DUMMY, O_WRONLY, 0200);
242 if (fd_smbw == -1) {
243 errno = EMFILE;
244 return NULL;
245 }
246
247 smbw_fix_path(fname, path);
248 fd_client = smbc_opendir(path);
249
250 if (fd_client < 0) {
251 (* smbw_libc.close)(fd_smbw);
252 return NULL;
253 }
254
255 smbw_fd_map[fd_smbw] = fd_client;
256 smbw_ref(fd_client, SMBW_RCT_Increment);
257 dirp = (DIR *) &smbw_fd_map[fd_smbw];
258 return dirp;
259}
260
261/*****************************************************
262read one entry from a directory
263*******************************************************/
264struct SMBW_dirent *smbw_readdir(DIR *dirp)
265{
266 int fd_smbw;
267 int fd_client;
268 struct smbc_dirent *dirent_internal;
269 static struct SMBW_dirent dirent_external;
270
271 fd_smbw = (int *) dirp - smbw_fd_map;
272 fd_client = smbw_fd_map[fd_smbw];
273
274 if ((dirent_internal = smbc_readdir(fd_client)) == NULL) {
275 return NULL;
276 }
277
278 dirent_external.d_ino = -1; /* not supported */
279 dirent_external.d_off = smbc_telldir(fd_client);
280 dirent_external.d_reclen = sizeof(struct SMBW_dirent);
281 dirent_external.d_type = dirent_internal->smbc_type;
282 smbw_strlcpy(dirent_external.d_name,
283 dirent_internal->name,
284 sizeof(dirent_external.d_name) - 1);
285 smbw_strlcpy(dirent_external.d_comment,
286 dirent_internal->comment,
287 sizeof(dirent_external.d_comment) - 1);
288
289 return &dirent_external;
290}
291
292/*****************************************************
293read one entry from a directory in a reentrant fashion
294ha! samba is not re-entrant, and neither is the
295libsmbclient library
296*******************************************************/
297int smbw_readdir_r(DIR *dirp,
298 struct SMBW_dirent *__restrict entry,
299 struct SMBW_dirent **__restrict result)
300{
301 SMBW_dirent *dirent;
302
303 dirent = smbw_readdir(dirp);
304
305 if (dirent != NULL) {
306 *entry = *dirent;
307 if (result != NULL) {
308 *result = entry;
309 }
310 return 0;
311 }
312
313 if (result != NULL) {
314 *result = NULL;
315 }
316 return EBADF;
317}
318
319
320/*****************************************************
321close a DIR*
322*******************************************************/
323int smbw_closedir(DIR *dirp)
324{
325 int fd_smbw = (int *) dirp - smbw_fd_map;
326 int fd_client = smbw_fd_map[fd_smbw];
327
328 (* smbw_libc.close)(fd_smbw);
329 if (smbw_ref(fd_client, SMBW_RCT_Decrement) > 0) {
330 return 0;
331 }
332 smbw_fd_map[fd_smbw] = -1;
333 return smbc_closedir(fd_client);
334}
335
336/*****************************************************
337seek in a directory
338*******************************************************/
339void smbw_seekdir(DIR *dirp, long long offset)
340{
341 int fd_smbw = (int *) dirp - smbw_fd_map;
342 int fd_client = smbw_fd_map[fd_smbw];
343
344 smbc_lseekdir(fd_client, offset);
345}
346
347/*****************************************************
348current loc in a directory
349*******************************************************/
350long long smbw_telldir(DIR *dirp)
351{
352 int fd_smbw = (int *) dirp - smbw_fd_map;
353 int fd_client = smbw_fd_map[fd_smbw];
354
355 return (long long) smbc_telldir(fd_client);
356}
Note: See TracBrowser for help on using the repository browser.