summaryrefslogtreecommitdiff
path: root/examples/libsmbclient/smbwrapper/smbw_dir.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/libsmbclient/smbwrapper/smbw_dir.c')
-rw-r--r--examples/libsmbclient/smbwrapper/smbw_dir.c355
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);
+}