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