2 * Auditing VFS module for samba. Log selected file operations to syslog
5 * Copyright (C) 2001, Brandon Stone, Amherst College, <bbstone@amherst.edu>.
6 * Copyright (C) 2002, Jeremy Allison - modified to make a VFS module.
7 * Copyright (C) 2002, Alexander Bokovoy - cascaded VFS adoption,
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
44 static struct vfs_ops default_vfs_ops; /* For passthrough operation */
45 static struct smb_vfs_handle_struct *recycle_handle;
46 static int recycle_unlink(connection_struct *, const char *);
47 static int recycle_connect(struct connection_struct *conn, const char *service, const char *user);
48 static void recycle_disconnect(struct connection_struct *conn);
50 static vfs_op_tuple recycle_ops[] = {
54 {recycle_connect, SMB_VFS_OP_CONNECT, SMB_VFS_LAYER_OPAQUE},
55 {recycle_disconnect, SMB_VFS_OP_DISCONNECT, SMB_VFS_LAYER_OPAQUE},
59 {recycle_unlink, SMB_VFS_OP_UNLINK, SMB_VFS_LAYER_OPAQUE},
61 {NULL, SMB_VFS_OP_NOOP, SMB_VFS_LAYER_NOOP}
64 /* VFS initialisation function. Return initialised vfs_op_tuple array back to SAMBA. */
66 vfs_op_tuple *vfs_init(int *vfs_version, struct vfs_ops *def_vfs_ops,
67 struct smb_vfs_handle_struct *vfs_handle)
69 *vfs_version = SMB_VFS_INTERFACE_VERSION;
70 memcpy(&default_vfs_ops, def_vfs_ops, sizeof(struct vfs_ops));
72 /* Remember vfs_id for storing private information at connect */
73 recycle_handle = vfs_handle;
78 /* VFS finalization function. */
79 void vfs_done(connection_struct *conn)
81 DEBUG(3,("vfs_done_recycle: called for connection %p\n",conn));
84 static int recycle_connect(struct connection_struct *conn, const char *service, const char *user)
88 DEBUG(3,("recycle_connect: called for service %s as user %s\n", service, user));
90 fstrcpy(recycle_bin, (const char *)lp_parm_string(lp_servicename(SNUM(conn)),"vfs","recycle bin"));
92 DEBUG(3,("recycle_connect: No options listed (vfs:recycle bin).\n" ));
93 return 0; /* No options. */
96 DEBUG(3,("recycle_connect: recycle name is %s\n", recycle_bin ));
98 recycle_handle->data = (void *)strdup(recycle_bin);
102 static void recycle_disconnect(struct connection_struct *conn)
104 SAFE_FREE(recycle_handle->data);
107 static BOOL recycle_XXX_exist(connection_struct *conn, const char *dname, BOOL isdir)
111 if (default_vfs_ops.stat(conn,dname,&st) != 0)
115 return S_ISDIR(st.st_mode) ? True : False;
117 return S_ISREG(st.st_mode) ? True : False;
120 static BOOL recycle_directory_exist(connection_struct *conn, const char *dname)
122 return recycle_XXX_exist(conn, dname, True);
125 static BOOL recycle_file_exist(connection_struct *conn, const char *fname)
127 return recycle_XXX_exist(conn, fname, False);
130 static SMB_OFF_T recycle_get_file_size(connection_struct *conn, const char *fname)
134 if (default_vfs_ops.stat(conn,fname,&st) != 0)
135 return (SMB_OFF_T)-1;
140 /********************************************************************
141 Check if file should be recycled
142 *********************************************************************/
144 static int recycle_unlink(connection_struct *conn, const char *inname)
150 int i=1, len, addlen;
152 SMB_BIG_UINT dfree,dsize,bsize;
155 pstrcpy(fname, inname);
157 if (recycle_handle->data)
158 fstrcpy(recycle_bin, (const char *)recycle_handle->data);
161 DEBUG(3, ("recycle bin: share parameter not set, purging %s...\n", fname));
162 return default_vfs_ops.unlink(conn,fname);
165 if(recycle_get_file_size(conn, fname) == 0) {
166 DEBUG(3, ("recycle bin: file %s is empty, purging...\n", fname));
167 return default_vfs_ops.unlink(conn,fname);
170 base = strrchr(fname, '/');
171 pstrcpy(bin, recycle_bin);
175 ext = strrchr(fname, '.');
178 ext = strrchr(base, '.');
179 pstrcat(bin, base+1);
181 DEBUG(3, ("recycle bin: base %s, ext %s, fname %s, bin %s\n", base, ext, fname, bin));
183 if(strcmp(fname,bin) == 0) {
184 DEBUG(3, ("recycle bin: file %s exists, purging...\n", fname));
185 return default_vfs_ops.unlink(conn,fname);
190 len = len - strlen(ext);
192 addlen = sizeof(pstring)-len-1;
193 while(recycle_file_exist(conn,bin)) {
194 slprintf(bin+len, addlen, " (Copy #%d)", i++);
198 DEBUG(3, ("recycle bin: moving source=%s to dest=%s\n", fname, bin));
199 default_vfs_ops.disk_free(conn,".",True,&bsize,&dfree,&dsize);
200 if((unsigned int)dfree > 0) {
202 if(!recycle_directory_exist(conn,recycle_bin)) {
203 DEBUG(3, ("recycle bin: directory %s nonexistant, creating...\n", recycle_bin));
204 if (default_vfs_ops.mkdir(conn,recycle_bin,dir_mask) == -1) {
205 DEBUG(3, ("recycle bin: unable to create directory %s. Error was %s\n",
206 recycle_bin, strerror(errno) ));
209 DEBUG(3, ("recycle bin: move %s -> %s\n", fname, bin));
211 ret = default_vfs_ops.rename(conn, fname, bin);
213 DEBUG(3, ("recycle bin: move error %d (%s)\n", errno, strerror(errno) ));
214 DEBUG(3, ("recycle bin: move failed, purging...\n"));
215 return default_vfs_ops.unlink(conn,fname);
219 DEBUG(3, ("recycle bin: move failed, purging...\n"));
220 return default_vfs_ops.unlink(conn,fname);