mars-nwe/nwattrib.c

330 lines
8.3 KiB
C

/* nwattrib.c 09-Feb-98 */
/* (C)opyright (C) 1998 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 <dirent.h>
#include "unxfile.h"
#include "nwvolume.h"
#include "connect.h"
#include "nwattrib.h"
static void put_attr_to_disk(int dev, ino_t inode, uint32 attrib)
{
char buf[255];
char battrib[255];
int l;
uint8 buf_uc[4];
U32_TO_BE32(inode, buf_uc);
l=sprintf(buf, "%s/%x/%x/%x/%x", path_attributes,
dev,
(int) buf_uc[0],
(int) buf_uc[1],
(int) buf_uc[2]);
seteuid(0);
unx_xmkdir(buf, 0755);
sprintf(buf+l, "/%x", (int) buf_uc[3]);
unlink(buf);
l=sprintf(battrib, "%08x", (unsigned int) attrib);
symlink(battrib, buf);
reseteuid();
}
static void free_attr_from_disk(int dev, ino_t inode)
{
char buf[255];
uint8 buf_uc[4];
U32_TO_BE32(inode, buf_uc);
sprintf(buf, "%s/%x/%x/%x/%x/%x", path_attributes,
dev,
(int) buf_uc[0],
(int) buf_uc[1],
(int) buf_uc[2],
(int) buf_uc[3]);
seteuid(0);
unlink(buf);
reseteuid();
}
static int get_attr_from_disk(int dev, ino_t inode, uint32 *attrib)
/* returns 0 if all ok */
{
char buf[255];
char battrib[255];
int l;
uint8 buf_uc[4];
U32_TO_BE32(inode, buf_uc);
sprintf(buf, "%s/%x/%x/%x/%x/%x", path_attributes,
dev,
(int) buf_uc[0],
(int) buf_uc[1],
(int) buf_uc[2],
(int) buf_uc[3]);
seteuid(0);
l=readlink(buf, battrib, 224);
reseteuid();
if (l > 0) {
unsigned int uattrib=0;
battrib[l]='\0';
if (1 == sscanf(battrib, "%x", &uattrib)) {
*attrib = uattrib;
return(0);
}
}
*attrib=0;
return(-1);
}
uint32 get_nw_attrib_dword(struct stat *stb, int voloptions)
/* returns full attrib_dword */
{
uint32 attrib=0;
int is_dir=S_ISDIR(stb->st_mode);
if (!is_dir && (voloptions & VOL_OPTION_IS_PIPE))
return(FILE_ATTR_SHARE|FILE_ATTR_A);
if (voloptions & VOL_OPTION_READONLY)
return((is_dir)?FILE_ATTR_DIR|FILE_ATTR_R:FILE_ATTR_R);
if (!get_attr_from_disk(stb->st_dev, stb->st_ino, &attrib)) {
if (is_dir) attrib |= FILE_ATTR_DIR;
else attrib &= (~FILE_ATTR_DIR);
} else {
if (is_dir)
attrib = FILE_ATTR_DIR;
else
attrib = FILE_ATTR_A; /* default archive flag */
}
if (act_uid) {
/* if not root */
int acc=get_real_access(stb);
if (!(acc & W_OK)) {
attrib |= FILE_ATTR_R; /* RO */
}
if (!(acc & R_OK)) {
attrib |= FILE_ATTR_H; /* We say hidden here */
}
}
return(attrib);
}
int set_nw_attrib_dword(struct stat *stb, int voloptions, uint32 attrib)
{
int is_dir=S_ISDIR(stb->st_mode);
if (voloptions & VOL_OPTION_READONLY)
return(-0x8c); /* no modify rights */
if (voloptions & VOL_OPTION_IS_PIPE)
return(0);
if (!(get_real_access(stb) & W_OK))
return(-0x8c); /* no modify rights */
if (is_dir) attrib |= 0x10;
else attrib &= ~0x10;
put_attr_to_disk(stb->st_dev, stb->st_ino, attrib);
return(0);
}
int set_nw_attrib_byte(struct stat *stb, int voloptions, int battrib)
{
int is_dir=S_ISDIR(stb->st_mode);
uint32 attrib,oldattrib;
if (voloptions & VOL_OPTION_READONLY)
return(-0x8c); /* no modify rights */
if (voloptions & VOL_OPTION_IS_PIPE)
return(0);
if (!(get_real_access(stb) & W_OK))
return(-0x8c); /* no modify rights */
oldattrib=get_nw_attrib_dword(stb, voloptions);
attrib = (oldattrib & ~0xff);
attrib |= battrib;
if (is_dir) attrib |= 0x10;
else attrib &= ~0x10;
if (attrib != oldattrib)
put_attr_to_disk(stb->st_dev, stb->st_ino, attrib);
return(0);
}
void set_nw_archive_bit(int dev, ino_t inode)
/* only called for files */
{
uint32 attrib;
if ( (!get_attr_from_disk(dev, inode, &attrib))
&& !(attrib & FILE_ATTR_A)) {
attrib|=FILE_ATTR_A;
put_attr_to_disk(dev, inode, attrib);
}
}
/* trustees */
static void put_trustee_to_disk(int dev, ino_t inode, uint32 id, int trustee)
{
char buf[255];
char btrustee[255];
int l;
uint8 buf_uc[4];
U32_TO_BE32(inode, buf_uc);
l=sprintf(buf, "%s/%x/%x/%x/%x/%x.t", path_attributes,
dev,
(int) buf_uc[0],
(int) buf_uc[1],
(int) buf_uc[2],
(int) buf_uc[3]);
seteuid(0);
unx_xmkdir(buf, 0755);
sprintf(buf+l, "/%x", (unsigned int) id);
unlink(buf);
l=sprintf(btrustee, "%04x", (unsigned int) trustee);
symlink(btrustee, buf);
reseteuid();
}
static void free_trustees_from_disk(int dev, ino_t inode)
{
char buf[255];
uint8 buf_uc[4];
U32_TO_BE32(inode, buf_uc);
sprintf(buf, "%s/%x/%x/%x/%x/%x.t", path_attributes,
dev,
(int) buf_uc[0],
(int) buf_uc[1],
(int) buf_uc[2],
(int) buf_uc[3]);
seteuid(0);
unx_xrmdir(buf);
reseteuid();
}
static int get_trustee_from_disk(int dev, ino_t inode, uint32 id)
{
char buf[255];
char btrustee[255];
int l;
uint8 buf_uc[4];
U32_TO_BE32(inode, buf_uc);
sprintf(buf, "%s/%x/%x/%x/%x/%x.t/%x", path_attributes,
dev,
(int) buf_uc[0],
(int) buf_uc[1],
(int) buf_uc[2],
(int) buf_uc[3],
(unsigned int) id);
seteuid(0);
l=readlink(buf, btrustee, 254);
reseteuid();
if (l > 0) {
unsigned int utrustee=0;
btrustee[l]='\0';
if (1 == sscanf(btrustee, "%x", &utrustee)) {
return((int)utrustee);
}
}
return(-1);
}
static int scan_trustees_from_disk(int dev, ino_t inode, int *offset,
int max_trustees, uint32 *trustee_ids, int *trustees)
/* returns count of trustees if all ok */
{
char buf[255];
int l;
int count=0;
uint8 buf_uc[4];
DIR *d;
U32_TO_BE32(inode, buf_uc);
l=sprintf(buf, "%s/%x/%x/%x/%x/%x.t", path_attributes,
dev,
(int) buf_uc[0],
(int) buf_uc[1],
(int) buf_uc[2],
(int) buf_uc[3]);
seteuid(0);
d = opendir(buf);
if (NULL != d) {
uint8 *p=buf+l;
struct dirent *dirbuff;
*p++ = '/';
l=0;
if ((unsigned int)(*offset) >= MAX_U16)
*offset=0;
while (count < max_trustees &&
(dirbuff = readdir(d)) != (struct dirent*)NULL){
if (l++ > *offset) {
if (dirbuff->d_ino) {
char btrustee[255];
int len;
unsigned int id;
if (1 == sscanf(dirbuff->d_name, "%x", &id) && id > 0) {
strcpy(p, dirbuff->d_name);
len=readlink(buf, btrustee, 254);
if (len > 0) {
unsigned int utrustee=0;
btrustee[len]='\0';
if (1 == sscanf(btrustee, "%x", &utrustee)) {
*trustee_ids++ = (uint32) id;
*trustees++ = (int) utrustee;
count++;
}
}
}
}
}
}
*offset=l;
closedir(d);
}
reseteuid();
return(count);
}
int get_own_trustee(int dev, ino_t inode, int look_for_trustee)
{
if (act_obj_id == 1){ /* supervisor */
if ( (look_for_trustee == TRUSTEE_S) || (look_for_trustee == TRUSTEE_M)
|| (look_for_trustee == (TRUSTEE_S | TRUSTEE_M)) )
return(look_for_trustee | TRUSTEE_S);
}
return(0);
}
int set_nw_trustee(int dev, ino_t inode, uint32 id, int trustee)
{
return(0);
#if 0
if (get_own_trustee(dev, inode, TRUSTEE_M) & (TRUSTEE_M | TRUSTEE_S)){
} else return(-0x8c); /* no modify privileges */
#endif
}
void free_nw_ext_inode(int dev, ino_t inode)
/* removes all attrib or trustees entries for files or dirs */
/* must be called after deleting nw file or dir */
{
free_attr_from_disk(dev, inode);
free_trustees_from_disk(dev, inode);
}