utils/src/test.c

263 lines
5.5 KiB
C

/* $Id$ */
/* Copyright (c) 2007 Pierre Pronchery <khorben@defora.org> */
/* This file is part of DeforaOS Unix utils */
/* utils is not free software; you can redistribute it and/or modify it under
* the terms of the Creative Commons Attribution-NonCommercial-ShareAlike 3.0
* Unported as published by the Creative Commons organization.
*
* utils 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 Creative Commons Attribution-NonCommercial-
* ShareAlike 3.0 Unported license for more details.
*
* You should have received a copy of the Creative Commons Attribution-
* NonCommercial-ShareAlike 3.0 along with utils; if not, browse to
* http://creativecommons.org/licenses/by-nc-sa/3.0/ */
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <pwd.h>
#include <grp.h>
/* test */
static int _test_single(char c, char * argv);
static int _test(int argc, char * argv[])
{
int i;
char * p;
for(i = 0; i < argc; i++)
{
p = argv[i];
if(strlen(p) == 2 && *p == '-')
{
if(i + 1 == argc)
return 1;
if(_test_single(*++p, argv[++i]) != 1)
return 1;
continue;
}
return 1;
}
return i == argc ? 0 : 1;
}
/* test_single */
/* b */ static int _is_file_block(char * pathname);
/* c */ static int _is_file_char(char * pathname);
/* d */ static int _is_file_dir(char * pathname);
/* e */ static int _is_file(char * pathname);
/* f */ static int _is_file_regular(char * pathname);
/* g */ static int _is_file_sgid(char * pathname);
/* h */ static int _is_file_symlink(char * pathname);
/* n */ static int _is_string_not_empty(char * string);
/* r */ static int _is_file_readable(char * pathname);
/* S */ static int _is_file_socket(char * pathname);
/* s */ static int _is_file_size(char * pathname);
/* w */ static int _is_file_writable(char * pathname);
/* x */ static int _is_file_executable(char * pathname);
/* z */ static int _is_string_empty(char * string);
static int _test_single(char c, char * argv)
{
switch(c)
{
case 'b':
return _is_file_block(argv);
case 'c':
return _is_file_char(argv);
case 'd':
return _is_file_dir(argv);
case 'e':
return _is_file(argv);
case 'f':
return _is_file_regular(argv);
case 'g':
return _is_file_sgid(argv);
case 'h':
case 'L':
return _is_file_symlink(argv);
case 'n':
return _is_string_not_empty(argv);
case 'r':
return _is_file_readable(argv);
case 'S':
return _is_file_socket(argv);
case 's':
return _is_file_size(argv);
case 'w':
return _is_file_writable(argv);
case 'x':
return _is_file_executable(argv);
case 'z':
return _is_string_empty(argv);
}
return 0;
}
static int _is_file_block(char * pathname)
{
struct stat st;
if(stat(pathname, &st) != 0)
return 0;
return S_ISBLK(st.st_mode) ? 1 : 0;
}
static int _is_file_char(char * pathname)
{
struct stat st;
if(stat(pathname, &st) != 0)
return 0;
return S_ISCHR(st.st_mode) ? 1 : 0;
}
static int _is_file_dir(char * pathname)
{
struct stat st;
if(stat(pathname, &st) != 0)
return 0;
return S_ISDIR(st.st_mode) ? 1 : 0;
}
static int _is_file(char * pathname)
{
struct stat st;
return stat(pathname, &st) == 0 ? 1 : 0;
}
static int _is_file_regular(char * pathname)
{
struct stat st;
if(stat(pathname, &st) != 0)
return 0;
return S_ISREG(st.st_mode) ? 1 : 0;
}
static int _is_file_sgid(char * pathname)
{
struct stat st;
if(stat(pathname, &st) != 0)
return 0;
return (st.st_mode & S_ISGID) ? 1 : 0; /* FIXME */
}
static int _is_file_symlink(char * pathname)
{
struct stat st;
if(lstat(pathname, &st) != 0)
return 0;
return S_ISLNK(st.st_mode) ? 1 : 0;
}
static int _is_string_not_empty(char * string)
{
return *string == '\0' ? 0 : 1;
}
static int _file_rwx_g(gid_t g);
static int _is_file_rwx(char * pathname, mode_t u, mode_t g, mode_t o)
{
struct stat st;
if(stat(pathname, &st) != 0)
return 0;
if(geteuid() == st.st_uid)
if((st.st_mode & u) != 0)
return 1;
if((st.st_mode & g) != 0)
{
if(_file_rwx_g(st.st_gid) == 1)
return 1;
if(geteuid() == st.st_uid)
return 0;
}
return (st.st_mode & o) != 0 ? 1 : 0;
}
static int _file_rwx_g(gid_t gid)
{
struct passwd * passwd;
struct group * group;
char ** p;
if((passwd = getpwuid(geteuid())) == NULL)
return 0;
if((group = getgrgid(gid)) == NULL)
return 0;
for(p = group->gr_mem; *p != NULL; p++)
if(strcmp(passwd->pw_name, *p) == 0)
return 1;
return 0;
}
static int _is_file_readable(char * pathname)
{
return _is_file_rwx(pathname, S_IRUSR, S_IRGRP, S_IROTH);
}
static int _is_file_socket(char * pathname)
{
struct stat st;
if(stat(pathname, &st) != 0)
return 0;
return (st.st_mode & S_IFSOCK) ? 1 : 0; /* FIXME */
}
static int _is_file_size(char * pathname)
{
struct stat st;
if(stat(pathname, &st) != 0)
return 0;
return st.st_size > 0 ? 1 : 0;
}
static int _is_string_empty(char * string)
{
return *string == '\0' ? 1 : 0;
}
static int _is_file_writable(char * pathname)
{
return _is_file_rwx(pathname, S_IWUSR, S_IWGRP, S_IWOTH);
}
static int _is_file_executable(char * pathname)
{
return _is_file_rwx(pathname, S_IXUSR, S_IXGRP, S_IXOTH);
}
/* usage */
static int _usage(void)
{
fputs("Usage: test [expression]\n\
[ [expression] ]\n", stderr);
return 1;
}
/* main */
int main(int argc, char * argv[])
{
if(argc == 1)
return 1; /* FIXME _usage(); */
if(strcmp(argv[0], "[") == 0)
if(strcmp(argv[--argc], "]") != 0)
return _usage();
return _test(argc - 1, argv + 1);
}