archie/prospero/lib/pcompat/stat.c
2024-05-27 16:13:40 +02:00

137 lines
3.5 KiB
C

/*
* Copyright (c) 1993, 1994 by the University of Southern California
*
* For copying and distribution information, please see the files
* <usc-license.h>
*/
#include <usc-license.h>
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef SOLARIS
#include <sys/syscall.h>
#else
#include <syscall.h>
#endif
#include <errno.h>
#include <pfs.h>
#include <pcompat.h>
#include <pmachine.h> /* for bzero */
#include <perrno.h> /* for testing against errors returned by
prospero subfunctions. */
static int stat_l(const char *path, struct stat *buf, int lflag);
/* syscall is not MT-safe (at least under Solaris) */
#ifndef PFS_THREADS
/* Call stat_l indicating normal stat */
int
stat(const char *path, struct stat *buf)
{
return(stat_l(path,buf,0));
}
/* Call stat_l indicating lstat */
int
lstat(const char *path, struct stat *buf)
{
return(stat_l(path,buf,1));
}
static int
stat_l(const char *path, struct stat *buf, int lflag)
{
VDIR_ST dir_st;
VDIR dir= &dir_st;
PATTRIB ap,nextap;
int tmp;
vdir_init(dir);
check_pfs_default();
/* If disabled, make system call */
if(pfs_enable == PMAP_DISABLE) {
return(syscall((lflag ? SYS_lstat : SYS_stat), path, buf));
}
if(pfs_enable == PMAP_COLON) {
if(*path == ':') path++;
else if(index(path,':'));
else return(syscall((lflag ? SYS_lstat : SYS_stat), path, buf));
}
if((pfs_enable == PMAP_ATSIGN_NF) || (pfs_enable == PMAP_ATSIGN)) {
if(*path == '@') {
path++;
return(syscall((lflag ? SYS_lstat : SYS_stat), path, buf));
}
}
bzero(buf,sizeof(struct stat));
buf->st_uid = (uid_t) -1;
buf->st_gid = (gid_t) -1;
p__compat_initialize();
/* I should probably choose better values for errno */
tmp = rd_vdir(path,0,dir,RVD_DFILE_ONLY|RVD_ATTRIB);
if((dir->links == NULL) || (tmp && (tmp != DIRSRV_NOT_DIRECTORY))) {
if(((tmp == PFS_DIR_NOT_FOUND)||(tmp == RVD_DIR_NOT_THERE)|| !tmp)&&
(pfs_enable == PMAP_ATSIGN_NF) && (*path == '/')) {
return(syscall((lflag ? SYS_lstat : SYS_stat), path, buf));
}
errno = ENOENT;
return(-1);
}
if(tmp == 0) buf->st_mode |= (S_IFDIR | 0555);
else buf->st_mode |= 0444;
if(strncmp(dir->links->target,"EXTERNAL",8) == 0) ap = NULL;
else ap = pget_at(dir->links,"#ALL");
/* If can't get real attributes, try those stored with link */
if((ap == NULL) && dir->links->lattrib) {
ap = dir->links->lattrib;
dir->links->lattrib = NULL;
}
while(ap) {
switch (*(ap->aname)) {
case 'L':
if((strcmp(ap->aname,"LAST-MODIFIED") == 0) &&
ap->avtype == ATR_SEQUENCE ) {
buf->st_mtime = asntotime(ap->value.sequence->token);
}
break;
case 'S':
if((strcmp(ap->aname,"SIZE") == 0) &&
ap->avtype == ATR_SEQUENCE) {
int size;
qsscanf(ap->value.sequence->token,"%d",&size);
buf->st_size = size;
/* The following is a good guess at number of blocks */
buf->st_blocks = (size+511) / 512;
}
break;
default:
break;
}
nextap = ap->next;
atfree(ap);
ap = nextap;
}
vllfree(dir->links);
vllfree(dir->ulinks);
return(0);
}
#endif /*PFS_THREADS*/