diff options
Diffstat (limited to 'examples/libsmbclient/smbwrapper/smbw_dir.c')
-rw-r--r-- | examples/libsmbclient/smbwrapper/smbw_dir.c | 355 |
1 files changed, 355 insertions, 0 deletions
diff --git a/examples/libsmbclient/smbwrapper/smbw_dir.c b/examples/libsmbclient/smbwrapper/smbw_dir.c new file mode 100644 index 0000000000..f3ec03e5a8 --- /dev/null +++ b/examples/libsmbclient/smbwrapper/smbw_dir.c @@ -0,0 +1,355 @@ +/* + Unix SMB/Netbios implementation. + Version 2.0 + SMB wrapper directory functions + Copyright (C) Andrew Tridgell 1998 + Copyright (C) Derrell Lipman 2003-2005 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "smbw.h" + +/***************************************************** +determine if a directory handle is a smb one +*******************************************************/ +int smbw_dirp(DIR * dirp) +{ + return ((char *) dirp >= (char *) smbw_fd_map && + (char *) dirp < (char *) &smbw_fd_map[__FD_SETSIZE] && + *(int *) dirp != -1); +} + + +/***************************************************** +a wrapper for getdents() +*******************************************************/ +int smbw_getdents(unsigned int fd_smbw, + struct SMBW_dirent *dirent_external, + int count) +{ + int remaining; + int fd_client = smbw_fd_map[fd_smbw]; + struct smbc_dirent *dirent_internal; + + + for (remaining = count; + remaining > sizeof(struct SMBW_dirent); + dirent_external++) { + + /* + * We do these one at a time because there's otherwise no way + * to limit how many smbc_getdents() will return for us, and + * if it returns too many, it also doesn't give us offsets to + * be able to seek back to where we need to be. In practice, + * this one-at-a-time retrieval isn't a problem because the + * time-consuming network transaction is all done at + * smbc_opendir() time. + */ + dirent_internal = smbc_readdir(fd_client); + if (dirent_internal == NULL) { + break; + } + + remaining -= sizeof(struct SMBW_dirent); + + dirent_external->d_ino = -1; /* not supported */ + dirent_external->d_off = smbc_telldir(fd_client); + dirent_external->d_reclen = sizeof(struct SMBW_dirent); + dirent_external->d_type = dirent_internal->smbc_type; + + strncpy(dirent_external->d_name, + dirent_internal->name, + sizeof(dirent_external->d_name) - 1); + strncpy(dirent_external->d_comment, + dirent_internal->comment, + sizeof(dirent_external->d_comment) - 1); + } + + return(count - remaining); +} + + +/***************************************************** +a wrapper for chdir() +*******************************************************/ +int smbw_chdir(const char *name) +{ + int simulate; + struct stat statbuf; + char path[PATH_MAX]; + char *p; + + SMBW_INIT(); + + if (!name) { + errno = EINVAL; + return -1; + } + + if (! smbw_path((char *) name)) { + if ((* smbw_libc.chdir)(name) == 0) { + *smbw_cwd = '\0'; + return 0; + } + + return -1; + } + + smbw_fix_path(name, path); + + /* ensure it exists */ + p = path + 6; /* look just past smb:// */ + simulate = (strchr(p, '/') == NULL); + + /* special case for full-network scan, workgroups, and servers */ + if (! simulate) { + + if (smbc_stat(path, &statbuf) < 0) { + return -1; + } + + /* ensure it's a directory */ + if (! S_ISDIR(statbuf.st_mode)) { + errno = ENOTDIR; + return -1; + } + } + + strncpy(smbw_cwd, path, PATH_MAX); + + /* we don't want the old directory to be busy */ + (* smbw_libc.chdir)("/"); + + return 0; +} + + +/***************************************************** +a wrapper for mkdir() +*******************************************************/ +int smbw_mkdir(const char *fname, mode_t mode) +{ + char path[PATH_MAX]; + + if (!fname) { + errno = EINVAL; + return -1; + } + + SMBW_INIT(); + + smbw_fix_path(fname, path); + return smbc_mkdir(path, mode); +} + +/***************************************************** +a wrapper for rmdir() +*******************************************************/ +int smbw_rmdir(const char *fname) +{ + char path[PATH_MAX]; + + if (!fname) { + errno = EINVAL; + return -1; + } + + SMBW_INIT(); + + smbw_fix_path(fname, path); + return smbc_rmdir(path); +} + + +/***************************************************** +a wrapper for getcwd() +*******************************************************/ +char *smbw_getcwd(char *buf, size_t size) +{ + SMBW_INIT(); + + if (*smbw_cwd == '\0') { + return (* smbw_libc.getcwd)(buf, size); + } + + if (buf == NULL) { + if (size == 0) { + size = strlen(smbw_cwd) + 1; + } + buf = malloc(size); + if (buf == NULL) { + errno = ENOMEM; + return NULL; + } + } + + strncpy(buf, smbw_cwd, size); + buf[size-1] = '\0'; + return buf; +} + +/***************************************************** +a wrapper for fchdir() +*******************************************************/ +int smbw_fchdir(int fd_smbw) +{ + int ret; + + SMBW_INIT(); + + if (! smbw_fd(fd_smbw)) { + ret = (* smbw_libc.fchdir)(fd_smbw); + (void) (* smbw_libc.getcwd)(smbw_cwd, PATH_MAX); + return ret; + } + + errno = EACCES; + return -1; +} + +/***************************************************** +open a directory on the server +*******************************************************/ +DIR *smbw_opendir(const char *fname) +{ + int fd_client; + int fd_smbw; + char path[PATH_MAX]; + DIR * dirp; + + SMBW_INIT(); + + if (!fname) { + errno = EINVAL; + return NULL; + } + + fd_smbw = (smbw_libc.open)(SMBW_DUMMY, O_WRONLY, 0200); + if (fd_smbw == -1) { + errno = EMFILE; + return NULL; + } + + smbw_fix_path(fname, path); + fd_client = smbc_opendir(path); + + if (fd_client < 0) { + (* smbw_libc.close)(fd_smbw); + return NULL; + } + + smbw_fd_map[fd_smbw] = fd_client; + smbw_ref(fd_client, SMBW_RCT_Increment); + dirp = (DIR *) &smbw_fd_map[fd_smbw]; + return dirp; +} + +/***************************************************** +read one entry from a directory +*******************************************************/ +struct SMBW_dirent *smbw_readdir(DIR *dirp) +{ + int fd_smbw; + int fd_client; + struct smbc_dirent *dirent_internal; + static struct SMBW_dirent dirent_external; + + fd_smbw = (int *) dirp - smbw_fd_map; + fd_client = smbw_fd_map[fd_smbw]; + + if ((dirent_internal = smbc_readdir(fd_client)) == NULL) { + return NULL; + } + + dirent_external.d_ino = -1; /* not supported */ + dirent_external.d_off = smbc_telldir(fd_client); + dirent_external.d_reclen = sizeof(struct SMBW_dirent); + dirent_external.d_type = dirent_internal->smbc_type; + strncpy(dirent_external.d_name, + dirent_internal->name, + sizeof(dirent_external.d_name) - 1); + strncpy(dirent_external.d_comment, + dirent_internal->comment, + sizeof(dirent_external.d_comment) - 1); + + return &dirent_external; +} + +/***************************************************** +read one entry from a directory in a reentrant fashion +ha! samba is not re-entrant, and neither is the +libsmbclient library +*******************************************************/ +int smbw_readdir_r(DIR *dirp, + struct SMBW_dirent *__restrict entry, + struct SMBW_dirent **__restrict result) +{ + SMBW_dirent *dirent; + + dirent = smbw_readdir(dirp); + + if (dirent != NULL) { + *entry = *dirent; + if (result != NULL) { + *result = entry; + } + return 0; + } + + if (result != NULL) { + *result = NULL; + } + return EBADF; +} + + +/***************************************************** +close a DIR* +*******************************************************/ +int smbw_closedir(DIR *dirp) +{ + int fd_smbw = (int *) dirp - smbw_fd_map; + int fd_client = smbw_fd_map[fd_smbw]; + + (* smbw_libc.close)(fd_smbw); + if (smbw_ref(fd_client, SMBW_RCT_Decrement) > 0) { + return 0; + } + smbw_fd_map[fd_smbw] = -1; + return smbc_closedir(fd_client); +} + +/***************************************************** +seek in a directory +*******************************************************/ +void smbw_seekdir(DIR *dirp, long long offset) +{ + int fd_smbw = (int *) dirp - smbw_fd_map; + int fd_client = smbw_fd_map[fd_smbw]; + + smbc_lseekdir(fd_client, offset); +} + +/***************************************************** +current loc in a directory +*******************************************************/ +long long smbw_telldir(DIR *dirp) +{ + int fd_smbw = (int *) dirp - smbw_fd_map; + int fd_client = smbw_fd_map[fd_smbw]; + + return (long long) smbc_telldir(fd_client); +} |