1
0
Files
irix-657m-src/eoe/cmd/bru/access.c
2022-09-29 17:59:04 +03:00

256 lines
6.2 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/************************************************************************
* *
* Copyright (c) 1984, Fred Fish *
* All Rights Reserved *
* *
* This software and/or documentation is protected by U.S. *
* Copyright Law (Title 17 United States Code). Unauthorized *
* reproduction and/or sales may result in imprisonment of up *
* to 1 year and fines of up to $10,000 (17 USC 506). *
* Copyright infringers may also be subject to civil liability. *
* *
************************************************************************
*/
/*
* FILE
*
* access.c routines for testing file accessibility
*
* SCCS
*
* @(#)access.c 9.11 5/11/88
*
*/
#include "autoconfig.h"
#include <stdio.h>
#include <string.h>
#if unix || xenix
#include <sys/types.h>
#include <sys/stat.h>
#endif
#include "typedefs.h"
#include "dbug.h"
#include "manifest.h"
#include "errors.h"
#include "config.h"
#include "macros.h"
extern int s_access (); /* Invoke the library "access" function */
extern char *s_strrchr (); /* Find last given character in string */
extern int s_readlink (); /* System function to read a symbolic link */
extern VOID bru_error (); /* Report an error to user */
/*
* FUNCTION
*
* file_access test for file accessible with given mode
*
* SYNOPSIS
*
* BOOLEAN file_access (name, amode, flag)
* char *name;
* int amode;
* BOOLEAN flag;
*
* DESCRIPTION
*
* Uses the process real user id and real group id to test the
* pathname pointed to by "name" for access in the given "amode".
* If access is denied and "flag" is TRUE, the user will be
* notified that access was denied.
*
* 4.2 BSD symbolic links introduce lots of problems. Since the
* system "access" routine goes through them to the real file, if a
* symbolic link points to a non-existant file, "access" will fail.
* This is not quite desirable. So, what we'll do is try a readlink
* on the file. If it succeeds, and the test was for existance or
* readability, then return true, otherwise false. (If a symlink exists,
* another call to symlink on it [i.e. "writing" to it] will fail.)
* The paragraph above causes directory access writablilty checks
* to fail, which is just plain wrong, and kept bru from restoring
* into a dir that was a symlink. Yuck; I *HATE* this code!
* I "fixed" this by always returning true for directory writability
* and letting later creates or whatever fail...
* Note that this routine is somewhat bogus now that bru is no longer
* setuid root; if someone choose to make it setuid root again, or
* invokes it from a setuid program, it will claim a lack of permission,
* even though it shouldn't. This has been fixed with a hack of
* setting the uid and gid to the effective uid and gid in init.c,
* rather than fixing all of the code that calls access.
* I've fixed some of the bogosities; the others call file_access
* mainly because file_stat() or some other routine prints an error
* message, and file_access doesn't...
*
*/
/*
* PSEUDO CODE
*
* Begin file_access
* If bad arguments then
* Warn user about bug
* End if
* If readlink on file succeeds then
* If access was read or existance then
* Result is TRUE
* Else
* Result is FALSE
* End if
* Else if specified access is allowed then
* Result is TRUE
* Else
* Result is false
* End if
* If Result is false and error reporting enabled then
* Switch on type of access mode
* Case "write access":
* Report write access failure
* Break
* Case "read access":
* Report read access failure
* Break
* Default:
* Report file does not exist
* Break
* End switch
* End if
* Return result
* End file_access
*
*/
BOOLEAN file_access (name, amode, flag)
char *name;
int amode;
BOOLEAN flag;
{
register int rtnval;
char buf[NAMESIZE];
DBUG_ENTER ("file_access");
if (name == NULL) {
bru_error (ERR_BUG, "file_access");
return FALSE;
}
DBUG_PRINT ("faccess", ("test %s for access %d", name, amode));
if (s_readlink (name, buf, sizeof buf) != SYS_ERROR) {
if (amode != A_WRITE) {
rtnval = TRUE;
} else {
rtnval = FALSE;
}
} else if (s_access (name, amode) != SYS_ERROR) {
rtnval = TRUE;
} else {
rtnval = FALSE;
}
if (rtnval == FALSE && flag) {
switch (amode) {
case A_WRITE:
bru_error (ERR_WACCESS, name);
break;
case A_READ:
bru_error (ERR_RACCESS, name);
break;
default:
bru_error (ERR_EACCESS, name);
break;
}
}
DBUG_PRINT ("faccess", ("result is %d", rtnval));
DBUG_RETURN (rtnval);
}
/*
* FUNCTION
*
* dir_access check the parent directory of a node for access
*
* SYNOPSIS
*
* BOOLEAN dir_access (name, amode, flag)
* char *name;
* int amode;
* BOOLEAN flag;
*
* DESCRIPTION
*
* Uses the process real user id and real group id to test the
* parent directory of the pathname pointed to by "name" for
* access in the given "amode". If access is denied and
* "flag" is TRUE, the user will be notified that access
* was denied.
*
* Returns TRUE or FALSE for access permitted or denied
* respectively.
*
*/
/*
* SEE My comments above about the bogosity of using access, especially
* when symlinks are involved....
* So now, all we do is check to see if it is a directory; if so,
* return TRUE, and let subsequent syscalls fail. The error messages
* may not be as great, but that's life...
*
* Preserve previous semantics that if no / in name, check current dir.
*
*/
BOOLEAN dir_access (name, amode, flag)
char *name;
int amode;
BOOLEAN flag;
{
struct stat64 s;
int rtnval, hadslash = 0;
char *d;
if(!name) {
bru_error(ERR_BUG, "dir_access");
return FALSE;
}
if(d = strrchr(name, '/')) {
if(d != name) {
hadslash = 1;
*d = '\0';
}
rtnval = stat64(name, &s); /* use stat, not lstat! */
if(hadslash)
*d = '/';
}
else
rtnval = stat64(".", &s); /* use stat, not lstat! */
if(rtnval || !IS_DIR(s.st_mode)) {
if(flag) switch (amode) {
case A_WRITE:
bru_error (ERR_WACCESS, name);
break;
case A_READ:
bru_error (ERR_RACCESS, name);
break;
default:
bru_error (ERR_EACCESS, name);
break;
}
return FALSE;
}
return TRUE;
}