• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.0.25b/examples/libsmbclient/smbwrapper/
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}
357