r23785: use the GPLv3 boilerplate as recommended by the FSF and the license text
[Samba/bb.git] / examples / libsmbclient / smbwrapper / smbw_dir.c
blob6e473bf0a33591456fe047ac4b1df519df78021e
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
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.
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.
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/>.
22 #include "smbw.h"
23 #include "bsd-strlfunc.h"
25 /*****************************************************
26 determine if a directory handle is a smb one
27 *******************************************************/
28 int smbw_dirp(DIR * dirp)
30 return ((char *) dirp >= (char *) smbw_fd_map &&
31 (char *) dirp < (char *) &smbw_fd_map[__FD_SETSIZE] &&
32 *(int *) dirp != -1);
36 /*****************************************************
37 a wrapper for getdents()
38 *******************************************************/
39 int smbw_getdents(unsigned int fd_smbw,
40 struct SMBW_dirent *dirent_external,
41 int count)
43 int remaining;
44 int fd_client = smbw_fd_map[fd_smbw];
45 struct smbc_dirent *dirent_internal;
48 for (remaining = count;
49 remaining > sizeof(struct SMBW_dirent);
50 dirent_external++) {
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.
61 dirent_internal = smbc_readdir(fd_client);
62 if (dirent_internal == NULL) {
63 break;
66 remaining -= sizeof(struct SMBW_dirent);
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;
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);
81 return(count - remaining);
85 /*****************************************************
86 a wrapper for chdir()
87 *******************************************************/
88 int smbw_chdir(const char *name)
90 int simulate;
91 struct stat statbuf;
92 char path[PATH_MAX];
93 char *p;
95 SMBW_INIT();
97 if (!name) {
98 errno = EINVAL;
99 return -1;
102 if (! smbw_path((char *) name)) {
103 if ((* smbw_libc.chdir)(name) == 0) {
104 *smbw_cwd = '\0';
105 return 0;
108 return -1;
111 smbw_fix_path(name, path);
113 /* ensure it exists */
114 p = path + 6; /* look just past smb:// */
115 simulate = (strchr(p, '/') == NULL);
117 /* special case for full-network scan, workgroups, and servers */
118 if (! simulate) {
120 if (smbc_stat(path, &statbuf) < 0) {
121 return -1;
124 /* ensure it's a directory */
125 if (! S_ISDIR(statbuf.st_mode)) {
126 errno = ENOTDIR;
127 return -1;
131 smbw_strlcpy(smbw_cwd, path, PATH_MAX);
133 /* we don't want the old directory to be busy */
134 (* smbw_libc.chdir)("/");
136 return 0;
140 /*****************************************************
141 a wrapper for mkdir()
142 *******************************************************/
143 int smbw_mkdir(const char *fname, mode_t mode)
145 char path[PATH_MAX];
147 if (!fname) {
148 errno = EINVAL;
149 return -1;
152 SMBW_INIT();
154 smbw_fix_path(fname, path);
155 return smbc_mkdir(path, mode);
158 /*****************************************************
159 a wrapper for rmdir()
160 *******************************************************/
161 int smbw_rmdir(const char *fname)
163 char path[PATH_MAX];
165 if (!fname) {
166 errno = EINVAL;
167 return -1;
170 SMBW_INIT();
172 smbw_fix_path(fname, path);
173 return smbc_rmdir(path);
177 /*****************************************************
178 a wrapper for getcwd()
179 *******************************************************/
180 char *smbw_getcwd(char *buf, size_t size)
182 SMBW_INIT();
184 if (*smbw_cwd == '\0') {
185 return (* smbw_libc.getcwd)(buf, size);
188 if (buf == NULL) {
189 if (size == 0) {
190 size = strlen(smbw_cwd) + 1;
192 buf = malloc(size);
193 if (buf == NULL) {
194 errno = ENOMEM;
195 return NULL;
199 smbw_strlcpy(buf, smbw_cwd, size);
200 buf[size-1] = '\0';
201 return buf;
204 /*****************************************************
205 a wrapper for fchdir()
206 *******************************************************/
207 int smbw_fchdir(int fd_smbw)
209 int ret;
211 SMBW_INIT();
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;
219 errno = EACCES;
220 return -1;
223 /*****************************************************
224 open a directory on the server
225 *******************************************************/
226 DIR *smbw_opendir(const char *fname)
228 int fd_client;
229 int fd_smbw;
230 char path[PATH_MAX];
231 DIR * dirp;
233 SMBW_INIT();
235 if (!fname) {
236 errno = EINVAL;
237 return NULL;
240 fd_smbw = (smbw_libc.open)(SMBW_DUMMY, O_WRONLY, 0200);
241 if (fd_smbw == -1) {
242 errno = EMFILE;
243 return NULL;
246 smbw_fix_path(fname, path);
247 fd_client = smbc_opendir(path);
249 if (fd_client < 0) {
250 (* smbw_libc.close)(fd_smbw);
251 return NULL;
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;
260 /*****************************************************
261 read one entry from a directory
262 *******************************************************/
263 struct SMBW_dirent *smbw_readdir(DIR *dirp)
265 int fd_smbw;
266 int fd_client;
267 struct smbc_dirent *dirent_internal;
268 static struct SMBW_dirent dirent_external;
270 fd_smbw = (int *) dirp - smbw_fd_map;
271 fd_client = smbw_fd_map[fd_smbw];
273 if ((dirent_internal = smbc_readdir(fd_client)) == NULL) {
274 return NULL;
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);
288 return &dirent_external;
291 /*****************************************************
292 read one entry from a directory in a reentrant fashion
293 ha! samba is not re-entrant, and neither is the
294 libsmbclient library
295 *******************************************************/
296 int smbw_readdir_r(DIR *dirp,
297 struct SMBW_dirent *__restrict entry,
298 struct SMBW_dirent **__restrict result)
300 SMBW_dirent *dirent;
302 dirent = smbw_readdir(dirp);
304 if (dirent != NULL) {
305 *entry = *dirent;
306 if (result != NULL) {
307 *result = entry;
309 return 0;
312 if (result != NULL) {
313 *result = NULL;
315 return EBADF;
319 /*****************************************************
320 close a DIR*
321 *******************************************************/
322 int smbw_closedir(DIR *dirp)
324 int fd_smbw = (int *) dirp - smbw_fd_map;
325 int fd_client = smbw_fd_map[fd_smbw];
327 (* smbw_libc.close)(fd_smbw);
328 if (smbw_ref(fd_client, SMBW_RCT_Decrement) > 0) {
329 return 0;
331 smbw_fd_map[fd_smbw] = -1;
332 return smbc_closedir(fd_client);
335 /*****************************************************
336 seek in a directory
337 *******************************************************/
338 void smbw_seekdir(DIR *dirp, long long offset)
340 int fd_smbw = (int *) dirp - smbw_fd_map;
341 int fd_client = smbw_fd_map[fd_smbw];
343 smbc_lseekdir(fd_client, offset);
346 /*****************************************************
347 current loc in a directory
348 *******************************************************/
349 long long smbw_telldir(DIR *dirp)
351 int fd_smbw = (int *) dirp - smbw_fd_map;
352 int fd_client = smbw_fd_map[fd_smbw];
354 return (long long) smbc_telldir(fd_client);