2 Unix SMB/Netbios implementation.
4 SMB wrapper directory functions
5 Copyright (C) Andrew Tridgell 1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "realcalls.h"
25 extern pstring smbw_cwd
;
26 extern fstring smbw_prefix
;
28 static struct smbw_dir
*smbw_dirs
;
30 extern struct bitmap
*smbw_file_bmap
;
34 /*****************************************************
35 map a fd to a smbw_dir structure
36 *******************************************************/
37 struct smbw_dir
*smbw_dir(int fd
)
41 for (dir
=smbw_dirs
;dir
;dir
=dir
->next
) {
42 if (dir
->fd
== fd
) return dir
;
47 /*****************************************************
48 check if a DIR* is one of ours
49 *******************************************************/
50 int smbw_dirp(DIR *dirp
)
52 struct smbw_dir
*d
= (struct smbw_dir
*)dirp
;
55 for (dir
=smbw_dirs
;dir
;dir
=dir
->next
) {
56 if (dir
== d
) return 1;
61 /*****************************************************
62 free a smbw_dir structure and all entries
63 *******************************************************/
64 static void free_dir(struct smbw_dir
*dir
)
69 if (dir
->path
) free(dir
->path
);
75 static struct smbw_dir
*cur_dir
;
77 /*****************************************************
78 add a entry to a directory listing
79 *******************************************************/
80 static void smbw_dir_add(struct file_info
*finfo
, const char *mask
, void *state
)
82 DEBUG(5,("%s\n", finfo
->name
));
84 if (cur_dir
->malloced
== cur_dir
->count
) {
85 cur_dir
->list
= (struct file_info
*)Realloc(cur_dir
->list
,
86 sizeof(cur_dir
->list
[0])*
87 (cur_dir
->count
+100));
92 cur_dir
->malloced
+= 100;
95 cur_dir
->list
[cur_dir
->count
] = *finfo
;
99 /*****************************************************
100 add a entry to a directory listing
101 *******************************************************/
102 static void smbw_share_add(const char *share
, uint32 type
,
103 const char *comment
, void *state
)
105 struct file_info finfo
;
107 if (strcmp(share
,"IPC$") == 0) return;
111 pstrcpy(finfo
.name
, share
);
112 finfo
.mode
= aRONLY
| aDIR
;
114 smbw_dir_add(&finfo
, NULL
, NULL
);
118 /*****************************************************
119 add a server to a directory listing
120 *******************************************************/
121 static void smbw_server_add(const char *name
, uint32 type
,
122 const char *comment
, void *state
)
124 struct file_info finfo
;
128 pstrcpy(finfo
.name
, name
);
129 finfo
.mode
= aRONLY
| aDIR
;
131 smbw_dir_add(&finfo
, NULL
, NULL
);
135 /*****************************************************
136 add a entry to a directory listing
137 *******************************************************/
138 static void smbw_printjob_add(struct print_job_info
*job
)
140 struct file_info finfo
;
144 pstrcpy(finfo
.name
, job
->name
);
145 finfo
.mode
= aRONLY
| aDIR
;
146 finfo
.mtime
= job
->t
;
147 finfo
.atime
= job
->t
;
148 finfo
.ctime
= job
->t
;
149 finfo
.uid
= nametouid(job
->user
);
151 finfo
.size
= job
->size
;
153 smbw_dir_add(&finfo
, NULL
, NULL
);
157 /*****************************************************
158 open a directory on the server
159 *******************************************************/
160 int smbw_dir_open(const char *fname
)
162 fstring server
, share
;
164 struct smbw_server
*srv
=NULL
;
165 struct smbw_dir
*dir
=NULL
;
177 /* work out what server they are after */
178 s
= smbw_parse_path(fname
, server
, share
, path
);
180 DEBUG(4,("dir_open share=%s\n", share
));
182 /* get a connection to the server */
183 srv
= smbw_server(server
, share
);
185 /* smbw_server sets errno */
189 dir
= (struct smbw_dir
*)malloc(sizeof(*dir
));
199 slprintf(mask
, sizeof(mask
)-1, "%s\\*", path
);
200 all_string_sub(mask
,"\\\\","\\",0);
202 if ((p
=strstr(srv
->server_name
,"#01"))) {
204 smbw_server_add(".",0,"",NULL
);
205 smbw_server_add("..",0,"",NULL
);
206 cli_NetServerEnum(&srv
->cli
, srv
->server_name
, SV_TYPE_DOMAIN_ENUM
,
207 smbw_server_add
,NULL
);
209 } else if ((p
=strstr(srv
->server_name
,"#1D"))) {
210 DEBUG(4,("doing NetServerEnum\n"));
212 smbw_server_add(".",0,"",NULL
);
213 smbw_server_add("..",0,"",NULL
);
214 cli_NetServerEnum(&srv
->cli
, srv
->server_name
, SV_TYPE_ALL
,
215 smbw_server_add
,NULL
);
217 } else if (strcmp(srv
->cli
.dev
,"IPC") == 0) {
218 DEBUG(4,("doing NetShareEnum\n"));
219 smbw_share_add(".",0,"",NULL
);
220 smbw_share_add("..",0,"",NULL
);
221 if (cli_RNetShareEnum(&srv
->cli
, smbw_share_add
,NULL
) < 0) {
222 errno
= smbw_errno(&srv
->cli
);
225 } else if (strncmp(srv
->cli
.dev
,"LPT",3) == 0) {
226 smbw_share_add(".",0,"",NULL
);
227 smbw_share_add("..",0,"",NULL
);
228 if (cli_print_queue(&srv
->cli
, smbw_printjob_add
) < 0) {
229 errno
= smbw_errno(&srv
->cli
);
234 if (strcmp(path
,"\\") == 0) {
235 smbw_share_add(".",0,"",NULL
);
236 smbw_share_add("..",0,"",NULL
);
239 if (cli_list(&srv
->cli
, mask
, aHIDDEN
|aSYSTEM
|aDIR
, smbw_dir_add
,NULL
) < 0) {
240 errno
= smbw_errno(&srv
->cli
);
247 fd
= open(SMBW_DUMMY
, O_WRONLY
);
253 if (bitmap_query(smbw_file_bmap
, fd
)) {
254 DEBUG(0,("ERROR: fd used in smbw_dir_open\n"));
259 DLIST_ADD(smbw_dirs
, dir
);
261 bitmap_set(smbw_file_bmap
, fd
);
265 dir
->path
= strdup(s
);
267 DEBUG(4,(" -> %d\n", dir
->count
));
279 /*****************************************************
280 a wrapper for fstat() on a directory
281 *******************************************************/
282 int smbw_dir_fstat(int fd
, struct stat
*st
)
284 struct smbw_dir
*dir
;
294 smbw_setup_stat(st
, "", dir
->count
*DIRP_SIZE
, aDIR
);
296 st
->st_dev
= dir
->srv
->dev
;
301 /*****************************************************
302 close a directory handle
303 *******************************************************/
304 int smbw_dir_close(int fd
)
306 struct smbw_dir
*dir
;
314 bitmap_clear(smbw_file_bmap
, dir
->fd
);
317 DLIST_REMOVE(smbw_dirs
, dir
);
324 /*****************************************************
325 a wrapper for getdents()
326 *******************************************************/
327 int smbw_getdents(unsigned int fd
, struct dirent
*dirp
, int count
)
329 struct smbw_dir
*dir
;
341 while (count
>=DIRP_SIZE
&& (dir
->offset
< dir
->count
)) {
342 #if HAVE_DIRENT_D_OFF
343 dirp
->d_off
= (dir
->offset
+1)*DIRP_SIZE
;
345 dirp
->d_reclen
= DIRP_SIZE
;
346 fstrcpy(&dirp
->d_name
[0], dir
->list
[dir
->offset
].name
);
347 dirp
->d_ino
= smbw_inode(dir
->list
[dir
->offset
].name
);
349 count
-= dirp
->d_reclen
;
350 #if HAVE_DIRENT_D_OFF
351 if (dir
->offset
== dir
->count
) {
355 dirp
= (struct dirent
*)(((char *)dirp
) + DIRP_SIZE
);
364 /*****************************************************
365 a wrapper for chdir()
366 *******************************************************/
367 int smbw_chdir(const char *name
)
369 struct smbw_server
*srv
;
370 fstring server
, share
;
378 len
= strlen(smbw_prefix
);
380 if (smbw_busy
) return real_chdir(name
);
389 DEBUG(4,("smbw_chdir(%s)\n", name
));
391 /* work out what server they are after */
392 cwd
= smbw_parse_path(name
, server
, share
, path
);
394 /* a special case - accept cd to /smb */
395 if (strncmp(cwd
, smbw_prefix
, len
-1) == 0 &&
400 if (strncmp(cwd
,smbw_prefix
,strlen(smbw_prefix
))) {
401 if (real_chdir(cwd
) == 0) {
407 /* get a connection to the server */
408 srv
= smbw_server(server
, share
);
410 /* smbw_server sets errno */
414 if (strncmp(srv
->cli
.dev
,"IPC",3) &&
415 strncmp(srv
->cli
.dev
,"LPT",3) &&
416 !smbw_getatr(srv
, path
,
417 &mode
, NULL
, NULL
, NULL
, NULL
, NULL
)) {
418 errno
= smbw_errno(&srv
->cli
);
422 if (!(mode
& aDIR
)) {
428 /* we don't want the old directory to be busy */
433 DEBUG(4,("set SMBW_CWD to %s\n", cwd
));
435 pstrcpy(smbw_cwd
, cwd
);
446 /*****************************************************
447 a wrapper for lseek() on directories
448 *******************************************************/
449 off_t
smbw_dir_lseek(int fd
, off_t offset
, int whence
)
451 struct smbw_dir
*dir
;
462 dir
->offset
= offset
/DIRP_SIZE
;
465 dir
->offset
+= offset
/DIRP_SIZE
;
468 dir
->offset
= (dir
->count
* DIRP_SIZE
) + offset
;
469 dir
->offset
/= DIRP_SIZE
;
473 ret
= dir
->offset
* DIRP_SIZE
;
475 DEBUG(4,(" -> %d\n", (int)ret
));
481 /*****************************************************
482 a wrapper for mkdir()
483 *******************************************************/
484 int smbw_mkdir(const char *fname
, mode_t mode
)
486 struct smbw_server
*srv
;
487 fstring server
, share
;
499 /* work out what server they are after */
500 smbw_parse_path(fname
, server
, share
, path
);
502 /* get a connection to the server */
503 srv
= smbw_server(server
, share
);
505 /* smbw_server sets errno */
509 if (!cli_mkdir(&srv
->cli
, path
)) {
510 errno
= smbw_errno(&srv
->cli
);
522 /*****************************************************
523 a wrapper for rmdir()
524 *******************************************************/
525 int smbw_rmdir(const char *fname
)
527 struct smbw_server
*srv
;
528 fstring server
, share
;
540 /* work out what server they are after */
541 smbw_parse_path(fname
, server
, share
, path
);
543 /* get a connection to the server */
544 srv
= smbw_server(server
, share
);
546 /* smbw_server sets errno */
550 if (!cli_rmdir(&srv
->cli
, path
)) {
551 errno
= smbw_errno(&srv
->cli
);
564 /*****************************************************
565 a wrapper for getcwd()
566 *******************************************************/
567 char *smbw_getcwd(char *buf
, size_t size
)
572 return (char *)real_getcwd(buf
, size
);
578 if (size
<= 0) size
= strlen(smbw_cwd
)+1;
579 buf
= (char *)malloc(size
);
587 if (strlen(smbw_cwd
) > size
-1) {
593 safe_strcpy(buf
, smbw_cwd
, size
);
599 /*****************************************************
600 a wrapper for fchdir()
601 *******************************************************/
602 int smbw_fchdir(unsigned int fd
)
604 struct smbw_dir
*dir
;
612 return chdir(dir
->path
);
615 ret
= real_fchdir(fd
);
624 /*****************************************************
625 open a directory on the server
626 *******************************************************/
627 DIR *smbw_opendir(const char *fname
)
633 fd
= smbw_dir_open(fname
);
642 return (DIR *)smbw_dir(fd
);
645 /*****************************************************
646 read one entry from a directory
647 *******************************************************/
648 struct dirent
*smbw_readdir(DIR *dirp
)
650 struct smbw_dir
*d
= (struct smbw_dir
*)dirp
;
656 if (smbw_getdents(d
->fd
, &dbuf
.de
, DIRP_SIZE
) > 0)
662 /*****************************************************
664 *******************************************************/
665 int smbw_closedir(DIR *dirp
)
667 struct smbw_dir
*d
= (struct smbw_dir
*)dirp
;
668 return smbw_close(d
->fd
);
671 /*****************************************************
673 *******************************************************/
674 void smbw_seekdir(DIR *dirp
, off_t offset
)
676 struct smbw_dir
*d
= (struct smbw_dir
*)dirp
;
677 smbw_dir_lseek(d
->fd
,offset
, SEEK_SET
);
680 /*****************************************************
681 current loc in a directory
682 *******************************************************/
683 off_t
smbw_telldir(DIR *dirp
)
685 struct smbw_dir
*d
= (struct smbw_dir
*)dirp
;
686 return smbw_dir_lseek(d
->fd
,0,SEEK_CUR
);