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, see <http://www.gnu.org/licenses/>.
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
] &&
36 /*****************************************************
37 a wrapper for getdents()
38 *******************************************************/
39 int smbw_getdents(unsigned int fd_smbw
,
40 struct SMBW_dirent
*dirent_external
,
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
);
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
) {
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 /*****************************************************
87 *******************************************************/
88 int smbw_chdir(const char *name
)
102 if (! smbw_path((char *) name
)) {
103 if ((* smbw_libc
.chdir
)(name
) == 0) {
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 */
120 if (smbc_stat(path
, &statbuf
) < 0) {
124 /* ensure it's a directory */
125 if (! S_ISDIR(statbuf
.st_mode
)) {
131 smbw_strlcpy(smbw_cwd
, path
, PATH_MAX
);
133 /* we don't want the old directory to be busy */
134 (* smbw_libc
.chdir
)("/");
140 /*****************************************************
141 a wrapper for mkdir()
142 *******************************************************/
143 int smbw_mkdir(const char *fname
, mode_t mode
)
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
)
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
)
184 if (*smbw_cwd
== '\0') {
185 return (* smbw_libc
.getcwd
)(buf
, size
);
190 size
= strlen(smbw_cwd
) + 1;
199 smbw_strlcpy(buf
, smbw_cwd
, size
);
204 /*****************************************************
205 a wrapper for fchdir()
206 *******************************************************/
207 int smbw_fchdir(int fd_smbw
)
213 if (! smbw_fd(fd_smbw
)) {
214 ret
= (* smbw_libc
.fchdir
)(fd_smbw
);
215 (void) (* smbw_libc
.getcwd
)(smbw_cwd
, PATH_MAX
);
223 /*****************************************************
224 open a directory on the server
225 *******************************************************/
226 DIR *smbw_opendir(const char *fname
)
240 fd_smbw
= (smbw_libc
.open
)(SMBW_DUMMY
, O_WRONLY
, 0200);
246 smbw_fix_path(fname
, path
);
247 fd_client
= smbc_opendir(path
);
250 (* smbw_libc
.close
)(fd_smbw
);
254 smbw_fd_map
[fd_smbw
] = fd_client
;
255 smbw_ref(fd_client
, SMBW_RCT_Increment
);
256 dirp
= (DIR *) &smbw_fd_map
[fd_smbw
];
260 /*****************************************************
261 read one entry from a directory
262 *******************************************************/
263 struct SMBW_dirent
*smbw_readdir(DIR *dirp
)
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
) {
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
295 *******************************************************/
296 int smbw_readdir_r(DIR *dirp
,
297 struct SMBW_dirent
*__restrict entry
,
298 struct SMBW_dirent
**__restrict result
)
302 dirent
= smbw_readdir(dirp
);
304 if (dirent
!= NULL
) {
306 if (result
!= NULL
) {
312 if (result
!= NULL
) {
319 /*****************************************************
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) {
331 smbw_fd_map
[fd_smbw
] = -1;
332 return smbc_closedir(fd_client
);
335 /*****************************************************
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
);