root/source4/ntvfs/cifs_posix_cli/svfs_util.c

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

DEFINITIONS

This source file includes following definitions.
  1. cifspsx_unix_path
  2. cifspsx_list_unix
  3. cifspsx_list
  4. cifspsx_file_utime
  5. cifspsx_unix_to_dos_attrib

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    simpler Samba VFS filesystem backend for clients which support the
   5    CIFS Unix Extensions or newer CIFS POSIX protocol extensions
   6 
   7 
   8    Copyright (C) Andrew Tridgell 2003
   9    Copyright (C) Steve French 2006
  10 
  11    This program is free software; you can redistribute it and/or modify
  12    it under the terms of the GNU General Public License as published by
  13    the Free Software Foundation; either version 3 of the License, or
  14    (at your option) any later version.
  15    
  16    This program is distributed in the hope that it will be useful,
  17    but WITHOUT ANY WARRANTY; without even the implied warranty of
  18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19    GNU General Public License for more details.
  20    
  21    You should have received a copy of the GNU General Public License
  22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  23 */
  24 /*
  25   utility functions for cifs posix backend
  26 */
  27 
  28 #include "includes.h"
  29 #include "system/filesys.h"
  30 #include "cifsposix.h"
  31 #include "system/time.h"
  32 #include "system/dir.h"
  33 #include "ntvfs/ntvfs.h"
  34 #include "ntvfs/cifs_posix_cli/proto.h"
  35 
  36 /*
  37   convert a windows path to a unix path - don't do any manging or case sensitive handling
  38 */
  39 char *cifspsx_unix_path(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
  40                      struct ntvfs_request *req, const char *name)
  41 {
  42         struct cifspsx_private *p = ntvfs->private_data;
  43         char *ret;
  44 
  45         if (*name != '\\') {
  46                 ret = talloc_asprintf(req, "%s/%s", p->connectpath, name);
  47         } else {
  48                 ret = talloc_asprintf(req, "%s%s", p->connectpath, name);
  49         }
  50         all_string_sub(ret, "\\", "/", 0);
  51 
  52         strlower(ret + strlen(p->connectpath));
  53 
  54         return ret;
  55 }
  56 
  57 
  58 /*
  59   read a directory and find all matching file names and stat info
  60   returned names are separate unix and DOS names. The returned names
  61   are relative to the directory
  62 */
  63 struct cifspsx_dir *cifspsx_list_unix(TALLOC_CTX *mem_ctx, struct ntvfs_request *req, const char *unix_path)
     /* [<][>][^][v][top][bottom][index][help] */
  64 {
  65         char *p, *mask;
  66         struct cifspsx_dir *dir;
  67         DIR *odir;
  68         struct dirent *dent;
  69         uint_t allocated = 0;
  70         char *low_mask;
  71 
  72         dir = talloc(mem_ctx, struct cifspsx_dir);
  73         if (!dir) { return NULL; }
  74 
  75         dir->count = 0;
  76         dir->files = 0;
  77 
  78         /* find the base directory */
  79         p = strrchr(unix_path, '/');
  80         if (!p) { return NULL; }
  81 
  82         dir->unix_dir = talloc_strndup(mem_ctx, unix_path, PTR_DIFF(p, unix_path));
  83         if (!dir->unix_dir) { return NULL; }
  84 
  85         /* the wildcard pattern is the last part */
  86         mask = p+1;
  87 
  88         low_mask = talloc_strdup(mem_ctx, mask);
  89         if (!low_mask) { return NULL; }
  90         strlower(low_mask);
  91 
  92         odir = opendir(dir->unix_dir);
  93         if (!odir) { return NULL; }
  94 
  95         while ((dent = readdir(odir))) {
  96                 uint_t i = dir->count;
  97                 char *full_name;
  98                 char *low_name;
  99 
 100                 if (strchr(dent->d_name, ':') && !strchr(unix_path, ':')) {
 101                         /* don't show streams in dir listing */
 102                         continue;
 103                 }
 104 
 105                 low_name = talloc_strdup(mem_ctx, dent->d_name);
 106                 if (!low_name) { continue; }
 107                 strlower(low_name);
 108 
 109                 /* check it matches the wildcard pattern */
 110                 if (ms_fnmatch(low_mask, low_name, PROTOCOL_NT1) != 0) {
 111                         continue;
 112                 }
 113                 
 114                 if (dir->count >= allocated) {
 115                         allocated = (allocated + 100) * 1.2;
 116                         dir->files = talloc_realloc(dir, dir->files, struct cifspsx_dirfile, allocated);
 117                         if (!dir->files) { 
 118                                 closedir(odir);
 119                                 return NULL;
 120                         }
 121                 }
 122 
 123                 dir->files[i].name = low_name;
 124                 if (!dir->files[i].name) { continue; }
 125 
 126                 asprintf(&full_name, "%s/%s", dir->unix_dir, dir->files[i].name);
 127                 if (!full_name) { continue; }
 128 
 129                 if (stat(full_name, &dir->files[i].st) == 0) { 
 130                         dir->count++;
 131                 }
 132 
 133                 free(full_name); 
 134         }
 135 
 136         closedir(odir);
 137 
 138         return dir;
 139 }
 140 
 141 /*
 142   read a directory and find all matching file names and stat info
 143   returned names are separate unix and DOS names. The returned names
 144   are relative to the directory
 145 */
 146 struct cifspsx_dir *cifspsx_list(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, const char *pattern)
     /* [<][>][^][v][top][bottom][index][help] */
 147 {
 148         struct cifspsx_private *p = ntvfs->private_data;
 149         char *unix_path;
 150 
 151         unix_path = cifspsx_unix_path(ntvfs, req, pattern);
 152         if (!unix_path) { return NULL; }
 153 
 154         return cifspsx_list_unix(p, req, unix_path);
 155 }
 156 
 157 
 158 /*******************************************************************
 159 set the time on a file via file descriptor
 160 *******************************************************************/
 161 int cifspsx_file_utime(int fd, struct utimbuf *times)
     /* [<][>][^][v][top][bottom][index][help] */
 162 {
 163         char *fd_path = NULL;
 164         int ret;
 165 
 166         asprintf(&fd_path, "/proc/self/%d", fd);
 167         if (!fd_path) {
 168                 errno = ENOMEM;
 169                 return -1;
 170         }
 171         
 172         ret = utime(fd_path, times);
 173         free(fd_path);
 174         return ret;
 175 }
 176 
 177 
 178 /*
 179   map a unix file attrib to a DOS attribute
 180 */
 181 uint16_t cifspsx_unix_to_dos_attrib(mode_t mode)
     /* [<][>][^][v][top][bottom][index][help] */
 182 {
 183         uint16_t ret = 0;
 184         if (S_ISDIR(mode)) ret |= FILE_ATTRIBUTE_DIRECTORY;
 185         if (!(mode & S_IWUSR)) ret |= FILE_ATTRIBUTE_READONLY;
 186         return ret;
 187 }
 188 

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