2 Unix SMB/Netbios implementation.
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, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "bsd-strlfunc.h"
26 /*****************************************************
27 determine if a directory handle is a smb one
28 *******************************************************/
29 int smbw_dirp(DIR * dirp)
31 return ((char *) dirp >= (char *) smbw_fd_map &&
32 (char *) dirp < (char *) &smbw_fd_map[__FD_SETSIZE] &&
37 /*****************************************************
38 a wrapper for getdents()
39 *******************************************************/
40 int smbw_getdents(unsigned int fd_smbw,
41 struct SMBW_dirent *dirent_external,
45 int fd_client = smbw_fd_map[fd_smbw];
46 struct smbc_dirent *dirent_internal;
49 for (remaining = count;
50 remaining > sizeof(struct SMBW_dirent);
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.
62 dirent_internal = smbc_readdir(fd_client);
63 if (dirent_internal == NULL) {
67 remaining -= sizeof(struct SMBW_dirent);
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;
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);
82 return(count - remaining);
86 /*****************************************************
88 *******************************************************/
89 int smbw_chdir(const char *name)
103 if (! smbw_path((char *) name)) {
104 if ((* smbw_libc.chdir)(name) == 0) {
112 smbw_fix_path(name, path);
114 /* ensure it exists */
115 p = path + 6; /* look just past smb:// */
116 simulate = (strchr(p, '/') == NULL);
118 /* special case for full-network scan, workgroups, and servers */
121 if (smbc_stat(path, &statbuf) < 0) {
125 /* ensure it's a directory */
126 if (! S_ISDIR(statbuf.st_mode)) {
132 smbw_strlcpy(smbw_cwd, path, PATH_MAX);
134 /* we don't want the old directory to be busy */
135 (* smbw_libc.chdir)("/");
141 /*****************************************************
142 a wrapper for mkdir()
143 *******************************************************/
144 int smbw_mkdir(const char *fname, mode_t mode)
155 smbw_fix_path(fname, path);
156 return smbc_mkdir(path, mode);
159 /*****************************************************
160 a wrapper for rmdir()
161 *******************************************************/
162 int smbw_rmdir(const char *fname)
173 smbw_fix_path(fname, path);
174 return smbc_rmdir(path);
178 /*****************************************************
179 a wrapper for getcwd()
180 *******************************************************/
181 char *smbw_getcwd(char *buf, size_t size)
185 if (*smbw_cwd == '\0') {
186 return (* smbw_libc.getcwd)(buf, size);
191 size = strlen(smbw_cwd) + 1;
200 smbw_strlcpy(buf, smbw_cwd, size);
205 /*****************************************************
206 a wrapper for fchdir()
207 *******************************************************/
208 int smbw_fchdir(int fd_smbw)
214 if (! smbw_fd(fd_smbw)) {
215 ret = (* smbw_libc.fchdir)(fd_smbw);
216 (void) (* smbw_libc.getcwd)(smbw_cwd, PATH_MAX);
224 /*****************************************************
225 open a directory on the server
226 *******************************************************/
227 DIR *smbw_opendir(const char *fname)
241 fd_smbw = (smbw_libc.open)(SMBW_DUMMY, O_WRONLY, 0200);
247 smbw_fix_path(fname, path);
248 fd_client = smbc_opendir(path);
251 (* smbw_libc.close)(fd_smbw);
255 smbw_fd_map[fd_smbw] = fd_client;
256 smbw_ref(fd_client, SMBW_RCT_Increment);
257 dirp = (DIR *) &smbw_fd_map[fd_smbw];
261 /*****************************************************
262 read one entry from a directory
263 *******************************************************/
264 struct SMBW_dirent *smbw_readdir(DIR *dirp)
268 struct smbc_dirent *dirent_internal;
269 static struct SMBW_dirent dirent_external;
271 fd_smbw = (int *) dirp - smbw_fd_map;
272 fd_client = smbw_fd_map[fd_smbw];
274 if ((dirent_internal = smbc_readdir(fd_client)) == NULL) {
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);
289 return &dirent_external;
292 /*****************************************************
293 read one entry from a directory in a reentrant fashion
294 ha! samba is not re-entrant, and neither is the
296 *******************************************************/
297 int smbw_readdir_r(DIR *dirp,
298 struct SMBW_dirent *__restrict entry,
299 struct SMBW_dirent **__restrict result)
303 dirent = smbw_readdir(dirp);
305 if (dirent != NULL) {
307 if (result != NULL) {
313 if (result != NULL) {
320 /*****************************************************
322 *******************************************************/
323 int smbw_closedir(DIR *dirp)
325 int fd_smbw = (int *) dirp - smbw_fd_map;
326 int fd_client = smbw_fd_map[fd_smbw];
328 (* smbw_libc.close)(fd_smbw);
329 if (smbw_ref(fd_client, SMBW_RCT_Decrement) > 0) {
332 smbw_fd_map[fd_smbw] = -1;
333 return smbc_closedir(fd_client);
336 /*****************************************************
338 *******************************************************/
339 void smbw_seekdir(DIR *dirp, long long offset)
341 int fd_smbw = (int *) dirp - smbw_fd_map;
342 int fd_client = smbw_fd_map[fd_smbw];
344 smbc_lseekdir(fd_client, offset);
347 /*****************************************************
348 current loc in a directory
349 *******************************************************/
350 long long smbw_telldir(DIR *dirp)
352 int fd_smbw = (int *) dirp - smbw_fd_map;
353 int fd_client = smbw_fd_map[fd_smbw];
355 return (long long) smbc_telldir(fd_client);