reverted to 1.24 and manually merged in changes from 2.2
[Samba.git] / examples / VFS / block / block.c
blob3c4f736e84913fcc0c74353471f19fdbf49c1907
1 /*
2 *
3 * Block access from links to dev mount points specified in PARAMCONF file
5 * Copyright (C) Ronald Kuetemeier, 2001
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "config.h"
23 #include <stdio.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <errno.h>
33 #ifdef HAVE_UTIME_H
34 #include <utime.h>
35 #endif
36 #ifdef HAVE_DIRENT_H
37 #include <dirent.h>
38 #endif
39 #include <syslog.h>
40 #ifdef HAVE_FCNTL_H
41 #include <fcntl.h>
42 #endif
45 #include <includes.h>
46 #include <vfs.h>
50 DIR *block_opendir(struct connection_struct *conn, char *fname);
51 int block_connect(struct connection_struct *conn, char *service, char *user);
52 void block_disconnect(struct connection_struct *conn);
55 /* VFS operations */
58 extern struct vfs_ops default_vfs_ops; /* For passthrough operation */
60 struct vfs_ops execute_vfs_ops = {
62 /* Disk operations */
64 block_connect,
65 block_disconnect,
66 NULL, /* disk free */
68 /* Directory operations */
70 block_opendir,
71 NULL, /* readdir */
72 NULL,
73 NULL,
74 NULL, /* closedir */
76 /* File operations */
78 NULL,
79 NULL,
80 NULL, /* read */
81 NULL, /* write */
82 NULL, /* lseek */
83 NULL,
84 NULL, /* fsync */
85 NULL, /* stat */
86 NULL, /* fstat */
87 NULL, /* lstat */
88 NULL,
89 NULL,
90 NULL,
91 NULL, /* chown */
92 NULL,
93 NULL, /* chdir */
94 NULL, /* getwd */
95 NULL, /* utime */
96 NULL, /* ftruncate */
97 NULL, /* lock */
98 NULL, /* fget_nt_acl */
99 NULL, /* get_nt_acl */
100 NULL, /* fset_nt_acl */
101 NULL, /* set_nt_acl */
102 NULL,
103 NULL
107 #ifndef PARAMCONF
108 #define PARAMCONF "/etc/samba-block.conf"
109 #endif
111 extern BOOL pm_process(char *FileName, BOOL (*sfunc)(char *), BOOL(*pfunc)(char * , char *));
113 //functions
115 BOOL enter_pblock_mount(char *dir);
116 BOOL get_section(char *sect);
117 BOOL get_parameter_value(char *param, char *value);
118 BOOL load_param(void);
119 BOOL search(struct stat *stat_buf);
120 BOOL dir_search(char *link, char *dir);
121 BOOL enter_pblock_dir(char *dir);
125 typedef struct block_dir
127 dev_t st_dev;
128 int str_len;
129 char *dir_name;
130 struct block_dir *next;
131 } block_dir;
134 static char *params[] = {"mount_point","dir_name"};
135 enum { MOUNT_POINT , DIR_NAME };
137 static struct block_dir *pblock_mountp = NULL;
138 static struct block_dir *pblock_dir = NULL;
143 * Load the conf file into a table
146 BOOL load_param(void)
149 if ((pm_process(PARAMCONF,&get_section,&get_parameter_value)) == TRUE)
151 return TRUE;
154 return FALSE;
160 * Enter the key and data into the list
164 BOOL enter_pblock_mount(char *dir)
166 struct stat stat_buf;
167 static struct block_dir *tmp_pblock;
170 if((stat(dir,&stat_buf)) != 0)
172 return FALSE;
175 if(pblock_mountp == NULL)
177 pblock_mountp = calloc(1, sizeof(block_dir));
178 if( pblock_mountp == NULL)
180 return FALSE;
182 tmp_pblock = pblock_mountp;
183 tmp_pblock->next = NULL;
185 }else
187 tmp_pblock->next = calloc(1, sizeof(block_dir));
188 if(tmp_pblock->next == NULL)
190 return FALSE;
192 tmp_pblock = tmp_pblock->next;
193 tmp_pblock->next = NULL;
198 tmp_pblock->st_dev = stat_buf.st_dev;
199 tmp_pblock->dir_name = strdup(dir);
202 return TRUE;
208 * Enter the key and data into the list
212 BOOL enter_pblock_dir(char *dir)
214 static struct block_dir *tmp_pblock;
217 if(pblock_dir == NULL)
219 pblock_dir = calloc(1, sizeof(block_dir));
220 if( pblock_dir == NULL)
222 return FALSE;
224 tmp_pblock = pblock_dir;
225 tmp_pblock->next = NULL;
227 }else
229 tmp_pblock->next = calloc(1, sizeof(block_dir));
230 if(tmp_pblock->next == NULL)
232 return FALSE;
234 tmp_pblock = tmp_pblock->next;
235 tmp_pblock->next = NULL;
240 tmp_pblock->dir_name = strdup(dir);
241 tmp_pblock->str_len = strlen(dir);
244 return TRUE;
252 * Function callback for config section names
255 BOOL get_section(char *sect)
257 return TRUE;
263 * Function callback for config parameter value pairs
267 BOOL get_parameter_value(char *param, char *value)
269 int i = 0, maxargs = sizeof(params) / sizeof(char *);
272 for( i= 0; i < maxargs; i++)
274 if (strcmp(param,params[i]) == 0)
276 switch(i)
278 case MOUNT_POINT :
279 enter_pblock_mount(value);
280 break;
281 case DIR_NAME :
282 enter_pblock_dir(value);
283 break;
284 default :
285 break;
290 return TRUE;
297 /* VFS initialisation function. Return initialised vfs_ops structure
298 back to SAMBA. */
300 struct vfs_ops *vfs_init(int *vfs_version)
302 *vfs_version = SMB_VFS_INTERFACE_VERSION;
304 return(&execute_vfs_ops);
309 * VFS connect and param file loading
312 int block_connect(struct connection_struct *conn, char *service, char *user)
314 if((load_param()) == FALSE)
317 return -1;
321 DEBUG(0,("%s connecting \n",conn->user));
323 return (default_vfs_ops.connect(conn, service,user));
327 * Free allocated structures and disconnect
332 void block_disconnect(struct connection_struct *conn)
335 struct block_dir *tmp_pblock = (pblock_mountp == NULL ? pblock_dir : pblock_mountp);
336 struct block_dir *free_pblock = NULL;
338 while(tmp_pblock != NULL)
340 free(tmp_pblock->dir_name);
341 free_pblock = tmp_pblock;
342 tmp_pblock = tmp_pblock->next;
343 free(free_pblock);
345 if(tmp_pblock == NULL && pblock_dir != NULL)
347 tmp_pblock = (pblock_mountp == NULL ? pblock_dir : NULL);
348 pblock_dir = NULL;
356 default_vfs_ops.disconnect(conn);
360 * VFS opendir
363 DIR *block_opendir(struct connection_struct *conn, char *fname)
366 char *dir_name = NULL;
367 struct stat stat_buf;
369 dir_name = alloca((strlen(conn->origpath) + strlen(fname) + 2) * sizeof(char));
371 pstrcpy(dir_name,conn->origpath);
372 pstrcat(dir_name, "/");
373 strncat(dir_name, fname, strcspn(fname,"/"));
375 if((lstat(dir_name,&stat_buf)) == 0)
377 if((S_ISLNK(stat_buf.st_mode)) == 1)
379 stat(dir_name,&stat_buf);
380 if((search(&stat_buf) || dir_search(dir_name, fname) ) == TRUE)
382 DEBUG(0,("%s used link to blocked dir: %s \n", conn->user, dir_name));
383 errno = EACCES;
384 return NULL;
389 return (default_vfs_ops.opendir(conn, fname));
394 * Find mount point to block in list
397 BOOL search(struct stat *stat_buf)
399 struct block_dir *tmp_pblock = pblock_mountp;
401 while(tmp_pblock != NULL)
404 if(tmp_pblock->st_dev == stat_buf->st_dev)
406 return TRUE;
408 tmp_pblock = tmp_pblock->next;
411 return FALSE;
416 * Find dir in list to block id the starting point is link from a share
419 BOOL dir_search(char *link, char *dir)
421 char buf[PATH_MAX +1], *ext_path;
422 int len = 0;
423 struct block_dir *tmp_pblock = pblock_dir;
425 if((len = readlink(link,buf,sizeof(buf))) == -1)
427 return TRUE;
429 }else
431 buf[len] = '\0';
435 if((ext_path = strchr(dir,'/')) != NULL)
437 pstrcat(buf,&ext_path[1]);
438 len = strlen(buf);
441 while(tmp_pblock != NULL)
443 if(len < tmp_pblock->str_len)
445 tmp_pblock = tmp_pblock->next;
446 continue;
449 if((strstr(buf,tmp_pblock->dir_name)) != NULL)
451 return TRUE;
453 tmp_pblock = tmp_pblock->next;
457 return FALSE;