mars-nwe/nwshare.c

166 lines
4.1 KiB
C

/* nwshare.c 21-Jul-97 */
/* (C)opyright (C) 1993,1997 Martin Stover, Marburg, Germany
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "net.h"
#include "nwvolume.h"
#include "nwfile.h"
#include "connect.h"
#include "unxfile.h"
#include "nwshare.h"
#define MAX_SH_OP_DEV 20
typedef struct {
int fd_r;
int fd_wr;
int in_use;
int dev;
} SH_OP_DEV;
static SH_OP_DEV sh_op_devs[MAX_SH_OP_DEV];
static int count_sh_op_dev=0;
char *path_share_lock_files=NULL;
int share_file(int dev, int inode, int sh_mode)
/* sh_mode
* 0 : remove share
* 1 : add_ro_r_share
* 4 : add_ro_w_share
*
* 2 : add_wr_r_share
* 8 : add_wr_w_share
* ----
* 0x10 : test
*/
{
int k = count_sh_op_dev;
int fr = -1;
int fo = -1;
int result = -1;
SH_OP_DEV *sod;
struct flock flockd;
while (k--) {
sod=&(sh_op_devs[k]);
if (sod->fd_r < 0) {
fr=k;
} else if (sod->dev == dev) {
fo=k;
break;
}
}
if ((!sh_mode) && fo==-1) {
XDPRINTF((1, 0, "Could not found share to remove"));
return(-1);
}
if (fo==-1 && fr==-1) {
if (count_sh_op_dev < MAX_SH_OP_DEV)
fr=count_sh_op_dev++;
else {
XDPRINTF((1, 0, "Too much 'share devs'"));
return(-1);
}
}
flockd.l_whence = SEEK_SET;
flockd.l_start = inode;
flockd.l_len = 1;
if (!sh_mode) {
sod=&(sh_op_devs[fo]);
flockd.l_type = F_UNLCK;
(void)fcntl(sod->fd_r, F_SETLK, &flockd);
(void)fcntl(sod->fd_wr, F_SETLK, &flockd);
if (--sod->in_use < 1) {
close(sod->fd_r);
close(sod->fd_wr);
sod->fd_r = -1;
sod->fd_wr = -1;
sod->dev = -1;
}
} else {
if (fo == -1) {
char buff[300];
int l;
sod=&(sh_op_devs[fr]);
if (NULL==path_share_lock_files) {
if (get_ini_entry(NULL, 41, buff, sizeof(buff)) && *buff)
new_str(path_share_lock_files, buff);
else
new_str(path_share_lock_files, "/var/spool/nwserv/.locks");
seteuid(0);
unx_xmkdir(path_share_lock_files, 0755);
reseteuid();
}
l=sprintf(buff, "%s/%x.r", path_share_lock_files, dev);
seteuid(0);
if (-1 < (sod->fd_r=open(buff, O_RDWR|O_CREAT, 0600)) ) {
buff[l-1]='w';
if (0 > (sod->fd_wr=open(buff, O_RDWR|O_CREAT, 0600) )){
close(sod->fd_r);
sod->fd_r=-1;
}
}
reseteuid();
if (sod->fd_r < 0) {
XDPRINTF((1, 0, "Cannot open sharefile=`%s`", buff));
return(-1);
}
sod->dev = dev;
} else
sod=&(sh_op_devs[fo]);
if (!(sh_mode&0x10)){
if (sh_mode & 1) {
flockd.l_type = (sh_mode & 4) ? F_WRLCK : F_RDLCK;
result=fcntl(sod->fd_r, F_SETLK, &flockd);
} else result=0;
if ((!result) && (sh_mode & 2) ) {
flockd.l_type = (sh_mode & 8) ? F_WRLCK : F_RDLCK;
result=fcntl(sod->fd_wr, F_SETLK, &flockd);
}
if (result) {
XDPRINTF((3, 0, "Cannot lock share sh_mode=%d", sh_mode));
} else {
sod->in_use++;
}
} else { /* only testing */
if (sh_mode & 1) {
flockd.l_type = (sh_mode & 4) ? F_WRLCK : F_RDLCK;
result=fcntl(sod->fd_r, F_GETLK, &flockd);
} else if (sh_mode & 2) {
flockd.l_type = (sh_mode & 8) ? F_WRLCK : F_RDLCK;
result=fcntl(sod->fd_wr, F_GETLK, &flockd);
} else result=-1;
return(flockd.l_type == F_UNLCK) ? 0 : -1;
}
}
return(result);
}