root/source4/ntvfs/posix/pvfs_mkdir.c

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

DEFINITIONS

This source file includes following definitions.
  1. pvfs_t2mkdir
  2. pvfs_mkdir
  3. pvfs_rmdir

   1 /* 
   2    Unix SMB/CIFS implementation.
   3 
   4    POSIX NTVFS backend - mkdir and rmdir
   5 
   6    Copyright (C) Andrew Tridgell 2004
   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 "includes.h"
  23 #include "system/dir.h"
  24 #include "vfs_posix.h"
  25 #include "librpc/gen_ndr/security.h"
  26 
  27 /*
  28   create a directory with EAs
  29 */
  30 static NTSTATUS pvfs_t2mkdir(struct pvfs_state *pvfs,
     /* [<][>][^][v][top][bottom][index][help] */
  31                              struct ntvfs_request *req, union smb_mkdir *md)
  32 {
  33         NTSTATUS status;
  34         struct pvfs_filename *name;
  35         mode_t mode;
  36 
  37         /* resolve the cifs name to a posix name */
  38         status = pvfs_resolve_name(pvfs, req, md->t2mkdir.in.path, 0, &name);
  39         if (!NT_STATUS_IS_OK(status)) {
  40                 return status;
  41         }
  42 
  43         if (name->exists) {
  44                 return NT_STATUS_OBJECT_NAME_COLLISION;
  45         }
  46 
  47         status = pvfs_access_check_parent(pvfs, req, name, SEC_DIR_ADD_FILE);
  48         if (!NT_STATUS_IS_OK(status)) {
  49                 return status;
  50         }
  51 
  52         mode = pvfs_fileperms(pvfs, FILE_ATTRIBUTE_DIRECTORY);
  53 
  54         if (mkdir(name->full_name, mode) == -1) {
  55                 return pvfs_map_errno(pvfs, errno);
  56         }
  57 
  58         pvfs_xattr_unlink_hook(pvfs, name->full_name);
  59 
  60         status = pvfs_resolve_name(pvfs, req, md->t2mkdir.in.path, 0, &name);
  61         if (!NT_STATUS_IS_OK(status)) {
  62                 return status;
  63         }
  64         if (!name->exists ||
  65             !(name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) {
  66                 return NT_STATUS_INTERNAL_ERROR;
  67         }
  68 
  69         /* setup an inherited acl from the parent */
  70         status = pvfs_acl_inherit(pvfs, req, name, -1);
  71         if (!NT_STATUS_IS_OK(status)) {
  72                 rmdir(name->full_name);
  73                 return status;
  74         }
  75 
  76         /* setup any EAs that were asked for */
  77         status = pvfs_setfileinfo_ea_set(pvfs, name, -1, 
  78                                          md->t2mkdir.in.num_eas,
  79                                          md->t2mkdir.in.eas);
  80         if (!NT_STATUS_IS_OK(status)) {
  81                 rmdir(name->full_name);
  82                 return status;
  83         }
  84 
  85         notify_trigger(pvfs->notify_context, 
  86                        NOTIFY_ACTION_ADDED, 
  87                        FILE_NOTIFY_CHANGE_DIR_NAME,
  88                        name->full_name);
  89 
  90         return NT_STATUS_OK;
  91 }
  92 
  93 /*
  94   create a directory
  95 */
  96 NTSTATUS pvfs_mkdir(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
  97                     struct ntvfs_request *req, union smb_mkdir *md)
  98 {
  99         struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
 100                                   struct pvfs_state);
 101         NTSTATUS status;
 102         struct pvfs_filename *name;
 103         mode_t mode;
 104 
 105         if (md->generic.level == RAW_MKDIR_T2MKDIR) {
 106                 return pvfs_t2mkdir(pvfs, req, md);
 107         }
 108 
 109         if (md->generic.level != RAW_MKDIR_MKDIR) {
 110                 return NT_STATUS_INVALID_LEVEL;
 111         }
 112 
 113         /* resolve the cifs name to a posix name */
 114         status = pvfs_resolve_name(pvfs, req, md->mkdir.in.path, 0, &name);
 115         if (!NT_STATUS_IS_OK(status)) {
 116                 return status;
 117         }
 118 
 119         if (name->exists) {
 120                 return NT_STATUS_OBJECT_NAME_COLLISION;
 121         }
 122 
 123         status = pvfs_access_check_parent(pvfs, req, name, SEC_DIR_ADD_FILE);
 124         if (!NT_STATUS_IS_OK(status)) {
 125                 return status;
 126         }
 127 
 128         mode = pvfs_fileperms(pvfs, FILE_ATTRIBUTE_DIRECTORY);
 129 
 130         if (mkdir(name->full_name, mode) == -1) {
 131                 return pvfs_map_errno(pvfs, errno);
 132         }
 133 
 134         pvfs_xattr_unlink_hook(pvfs, name->full_name);
 135 
 136         /* setup an inherited acl from the parent */
 137         status = pvfs_acl_inherit(pvfs, req, name, -1);
 138         if (!NT_STATUS_IS_OK(status)) {
 139                 rmdir(name->full_name);
 140                 return status;
 141         }
 142 
 143         notify_trigger(pvfs->notify_context, 
 144                        NOTIFY_ACTION_ADDED, 
 145                        FILE_NOTIFY_CHANGE_DIR_NAME,
 146                        name->full_name);
 147 
 148         return NT_STATUS_OK;
 149 }
 150 
 151 /*
 152   remove a directory
 153 */
 154 NTSTATUS pvfs_rmdir(struct ntvfs_module_context *ntvfs,
     /* [<][>][^][v][top][bottom][index][help] */
 155                     struct ntvfs_request *req, struct smb_rmdir *rd)
 156 {
 157         struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
 158                                   struct pvfs_state);
 159         NTSTATUS status;
 160         struct pvfs_filename *name;
 161 
 162         /* resolve the cifs name to a posix name */
 163         status = pvfs_resolve_name(pvfs, req, rd->in.path, 0, &name);
 164         if (!NT_STATUS_IS_OK(status)) {
 165                 return status;
 166         }
 167 
 168         if (!name->exists) {
 169                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
 170         }
 171 
 172         status = pvfs_access_check_simple(pvfs, req, name, SEC_STD_DELETE);
 173         if (!NT_STATUS_IS_OK(status)) {
 174                 return status;
 175         }
 176 
 177         status = pvfs_xattr_unlink_hook(pvfs, name->full_name);
 178         if (!NT_STATUS_IS_OK(status)) {
 179                 return status;
 180         }
 181 
 182         if (rmdir(name->full_name) == -1) {
 183                 /* some olders systems don't return ENOTEMPTY to rmdir() */
 184                 if (errno == EEXIST) {
 185                         return NT_STATUS_DIRECTORY_NOT_EMPTY;
 186                 }
 187                 return pvfs_map_errno(pvfs, errno);
 188         }
 189 
 190         notify_trigger(pvfs->notify_context, 
 191                        NOTIFY_ACTION_REMOVED, 
 192                        FILE_NOTIFY_CHANGE_DIR_NAME,
 193                        name->full_name);
 194 
 195         return NT_STATUS_OK;
 196 }

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