root/examples/libsmbclient/smbwrapper/smbw_dir.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. smbw_dirp
  2. smbw_getdents
  3. smbw_chdir
  4. smbw_mkdir
  5. smbw_rmdir
  6. smbw_getcwd
  7. smbw_fchdir
  8. smbw_opendir
  9. smbw_readdir
  10. smbw_readdir_r
  11. smbw_closedir
  12. smbw_seekdir
  13. smbw_telldir

   1 /* 
   2    Unix SMB/Netbios implementation.
   3    Version 2.0
   4    SMB wrapper directory functions
   5    Copyright (C) Andrew Tridgell 1998
   6    Copyright (C) Derrell Lipman 2003-2005
   7    
   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.
  12    
  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.
  17    
  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/>.
  20 */
  21 
  22 #include "smbw.h"
  23 #include "bsd-strlfunc.h"
  24 
  25 /***************************************************** 
  26 determine if a directory handle is a smb one
  27 *******************************************************/
  28 int smbw_dirp(DIR * dirp)
     /* [<][>][^][v][top][bottom][index][help] */
  29 {
  30         return ((char *) dirp >= (char *) smbw_fd_map &&
  31                 (char *) dirp < (char *) &smbw_fd_map[__FD_SETSIZE] &&
  32                 *(int *) dirp != -1);
  33 }
  34 
  35 
  36 /***************************************************** 
  37 a wrapper for getdents()
  38 *******************************************************/
  39 int smbw_getdents(unsigned int fd_smbw,
     /* [<][>][^][v][top][bottom][index][help] */
  40                   struct SMBW_dirent *dirent_external,
  41                   int count)
  42 {
  43         int remaining;
  44         int fd_client = smbw_fd_map[fd_smbw];
  45         struct smbc_dirent *dirent_internal;
  46 
  47 
  48         for (remaining = count;
  49              remaining > sizeof(struct SMBW_dirent);
  50              dirent_external++) {
  51 
  52                 /*
  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.
  60                  */
  61                 dirent_internal = smbc_readdir(fd_client);
  62                 if (dirent_internal == NULL) {
  63                         break;
  64                 }
  65 
  66                 remaining -= sizeof(struct SMBW_dirent);
  67 
  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;
  72 
  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);
  79         }
  80 
  81         return(count - remaining);
  82 }
  83 
  84 
  85 /***************************************************** 
  86 a wrapper for chdir()
  87 *******************************************************/
  88 int smbw_chdir(const char *name)
     /* [<][>][^][v][top][bottom][index][help] */
  89 {
  90         int simulate;
  91         struct stat statbuf;
  92         char path[PATH_MAX];
  93         char *p;
  94 
  95         SMBW_INIT();
  96 
  97         if (!name) {
  98                 errno = EINVAL;
  99                 return -1;
 100         }
 101 
 102         if (! smbw_path((char *) name)) {
 103                 if ((* smbw_libc.chdir)(name) == 0) {
 104                         *smbw_cwd = '\0';
 105                         return 0;
 106                 }
 107 
 108                 return -1;
 109         }
 110 
 111         smbw_fix_path(name, path);
 112 
 113         /* ensure it exists */
 114         p = path + 6;           /* look just past smb:// */
 115         simulate = (strchr(p, '/') == NULL);
 116 
 117         /* special case for full-network scan, workgroups, and servers */
 118         if (! simulate) {
 119             
 120             if (smbc_stat(path, &statbuf) < 0) {
 121                 return -1;
 122             }
 123             
 124             /* ensure it's a directory */
 125             if (! S_ISDIR(statbuf.st_mode)) {
 126                 errno = ENOTDIR;
 127                 return -1;
 128             }
 129         }
 130 
 131         smbw_strlcpy(smbw_cwd, path, PATH_MAX);
 132 
 133         /* we don't want the old directory to be busy */
 134         (* smbw_libc.chdir)("/");
 135 
 136         return 0;
 137 }
 138 
 139 
 140 /***************************************************** 
 141 a wrapper for mkdir()
 142 *******************************************************/
 143 int smbw_mkdir(const char *fname, mode_t mode)
     /* [<][>][^][v][top][bottom][index][help] */
 144 {
 145         char path[PATH_MAX];
 146 
 147         if (!fname) {
 148                 errno = EINVAL;
 149                 return -1;
 150         }
 151 
 152         SMBW_INIT();
 153 
 154         smbw_fix_path(fname, path);
 155         return smbc_mkdir(path, mode);
 156 }
 157 
 158 /***************************************************** 
 159 a wrapper for rmdir()
 160 *******************************************************/
 161 int smbw_rmdir(const char *fname)
     /* [<][>][^][v][top][bottom][index][help] */
 162 {
 163         char path[PATH_MAX];
 164 
 165         if (!fname) {
 166                 errno = EINVAL;
 167                 return -1;
 168         }
 169 
 170         SMBW_INIT();
 171 
 172         smbw_fix_path(fname, path);
 173         return smbc_rmdir(path);
 174 }
 175 
 176 
 177 /***************************************************** 
 178 a wrapper for getcwd()
 179 *******************************************************/
 180 char *smbw_getcwd(char *buf, size_t size)
     /* [<][>][^][v][top][bottom][index][help] */
 181 {
 182         SMBW_INIT();
 183 
 184         if (*smbw_cwd == '\0') {
 185                 return (* smbw_libc.getcwd)(buf, size);
 186         }
 187 
 188         if (buf == NULL) {
 189                 if (size == 0) {
 190                         size = strlen(smbw_cwd) + 1;
 191                 }
 192                 buf = malloc(size);
 193                 if (buf == NULL) {
 194                         errno = ENOMEM;
 195                         return NULL;
 196                 }
 197         }
 198 
 199         smbw_strlcpy(buf, smbw_cwd, size);
 200         buf[size-1] = '\0';
 201         return buf;
 202 }
 203 
 204 /***************************************************** 
 205 a wrapper for fchdir()
 206 *******************************************************/
 207 int smbw_fchdir(int fd_smbw)
     /* [<][>][^][v][top][bottom][index][help] */
 208 {
 209         int ret;
 210 
 211         SMBW_INIT();
 212 
 213         if (! smbw_fd(fd_smbw)) {
 214                 ret = (* smbw_libc.fchdir)(fd_smbw);
 215                 (void) (* smbw_libc.getcwd)(smbw_cwd, PATH_MAX);
 216                 return ret;
 217         }
 218 
 219         errno = EACCES;
 220         return -1;
 221 }
 222 
 223 /***************************************************** 
 224 open a directory on the server
 225 *******************************************************/
 226 DIR *smbw_opendir(const char *fname)
     /* [<][>][^][v][top][bottom][index][help] */
 227 {
 228         int fd_client;
 229         int fd_smbw;
 230         char path[PATH_MAX];
 231         DIR * dirp;
 232 
 233         SMBW_INIT();
 234 
 235         if (!fname) {
 236                 errno = EINVAL;
 237                 return NULL;
 238         }
 239 
 240         fd_smbw = (smbw_libc.open)(SMBW_DUMMY, O_WRONLY, 0200);
 241         if (fd_smbw == -1) {
 242                 errno = EMFILE;
 243                 return NULL;
 244         }
 245 
 246         smbw_fix_path(fname, path);
 247         fd_client =  smbc_opendir(path);
 248 
 249         if (fd_client < 0) {
 250                 (* smbw_libc.close)(fd_smbw);
 251                 return NULL;
 252         }
 253 
 254         smbw_fd_map[fd_smbw] = fd_client;
 255         smbw_ref(fd_client, SMBW_RCT_Increment);
 256         dirp = (DIR *) &smbw_fd_map[fd_smbw];
 257         return dirp;
 258 }
 259 
 260 /***************************************************** 
 261 read one entry from a directory
 262 *******************************************************/
 263 struct SMBW_dirent *smbw_readdir(DIR *dirp)
     /* [<][>][^][v][top][bottom][index][help] */
 264 {
 265         int fd_smbw;
 266         int fd_client;
 267         struct smbc_dirent *dirent_internal;
 268         static struct SMBW_dirent dirent_external;
 269 
 270         fd_smbw = (int *) dirp - smbw_fd_map;
 271         fd_client = smbw_fd_map[fd_smbw];
 272 
 273         if ((dirent_internal = smbc_readdir(fd_client)) == NULL) {
 274                 return NULL;
 275         }
 276  
 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);
 287 
 288         return &dirent_external;
 289 }
 290 
 291 /***************************************************** 
 292 read one entry from a directory in a reentrant fashion
 293 ha!  samba is not re-entrant, and neither is the
 294 libsmbclient library
 295 *******************************************************/
 296 int smbw_readdir_r(DIR *dirp,
     /* [<][>][^][v][top][bottom][index][help] */
 297                    struct SMBW_dirent *__restrict entry,
 298                    struct SMBW_dirent **__restrict result)
 299 {
 300         SMBW_dirent *dirent;
 301 
 302         dirent = smbw_readdir(dirp);
 303 
 304         if (dirent != NULL) {
 305                 *entry = *dirent;
 306                 if (result != NULL) {
 307                         *result = entry;
 308                 }
 309                 return 0;
 310         }
 311 
 312         if (result != NULL) {
 313                 *result = NULL;
 314         }
 315         return EBADF;
 316 }
 317 
 318 
 319 /***************************************************** 
 320 close a DIR*
 321 *******************************************************/
 322 int smbw_closedir(DIR *dirp)
     /* [<][>][^][v][top][bottom][index][help] */
 323 {
 324         int fd_smbw = (int *) dirp - smbw_fd_map;
 325         int fd_client = smbw_fd_map[fd_smbw];
 326 
 327         (* smbw_libc.close)(fd_smbw);
 328         if (smbw_ref(fd_client, SMBW_RCT_Decrement) > 0) {
 329                 return 0;
 330         }
 331         smbw_fd_map[fd_smbw] = -1;
 332         return smbc_closedir(fd_client);
 333 }
 334 
 335 /***************************************************** 
 336 seek in a directory
 337 *******************************************************/
 338 void smbw_seekdir(DIR *dirp, long long offset)
     /* [<][>][^][v][top][bottom][index][help] */
 339 {
 340         int fd_smbw = (int *) dirp - smbw_fd_map;
 341         int fd_client = smbw_fd_map[fd_smbw];
 342 
 343         smbc_lseekdir(fd_client, offset);
 344 }
 345 
 346 /***************************************************** 
 347 current loc in a directory
 348 *******************************************************/
 349 long long smbw_telldir(DIR *dirp)
     /* [<][>][^][v][top][bottom][index][help] */
 350 {
 351         int fd_smbw = (int *) dirp - smbw_fd_map;
 352         int fd_client = smbw_fd_map[fd_smbw];
 353 
 354         return (long long) smbc_telldir(fd_client);
 355 }

/* [<][>][^][v][top][bottom][index][help] */