134 lines
2.8 KiB
C
134 lines
2.8 KiB
C
/* $Id$ */
|
|
/* Copyright (c) 2009 Pierre Pronchery <khorben@defora.org> */
|
|
/* This file is part of DeforaOS Unix utils */
|
|
/* 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, version 3 of the License.
|
|
*
|
|
* 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, see <http://www.gnu.org/licenses/>. */
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
|
|
/* constants */
|
|
#ifndef PROGNAME
|
|
# define PROGNAME "file"
|
|
#endif
|
|
|
|
|
|
/* prefs */
|
|
typedef int Prefs;
|
|
#define FILE_PREFS_h 1
|
|
#define FILE_PREFS_m 2
|
|
#define FILE_PREFS_M 4
|
|
#define FILE_PREFS_d 6
|
|
#define FILE_PREFS_i 8
|
|
|
|
|
|
/* file */
|
|
static int _file_do(Prefs * p, char const * filename);
|
|
static int _file(Prefs * p, int argc, char * argv[])
|
|
{
|
|
int ret = 0;
|
|
int i;
|
|
|
|
for(i = 0; i < argc; i++)
|
|
ret += _file_do(p, argv[i]);
|
|
return ret;
|
|
}
|
|
|
|
static int _file_do(Prefs * p, char const * filename)
|
|
{
|
|
struct stat st;
|
|
int (*statfunc)(const char *, struct stat*) = *p & FILE_PREFS_h
|
|
? lstat : stat;
|
|
|
|
printf("%s: ", filename);
|
|
if(statfunc(filename, &st) != 0)
|
|
{
|
|
puts("cannot open file");
|
|
return 0;
|
|
}
|
|
if(S_ISLNK(st.st_mode))
|
|
fputs("symbolic link to ", stdout);
|
|
if(S_ISBLK(st.st_mode))
|
|
fputs("block special ", stdout);
|
|
else if(S_ISCHR(st.st_mode))
|
|
fputs("character special ", stdout);
|
|
else if(S_ISDIR(st.st_mode))
|
|
fputs("directory ", stdout);
|
|
else if(S_ISFIFO(st.st_mode))
|
|
fputs("fifo ", stdout);
|
|
else if(S_ISSOCK(st.st_mode))
|
|
fputs("socket ", stdout);
|
|
else
|
|
{
|
|
if(*p & FILE_PREFS_i)
|
|
fputs("regular file ", stdout);
|
|
else if(st.st_size == 0)
|
|
fputs("empty ", stdout);
|
|
if(st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))
|
|
fputs("executable ", stdout);
|
|
}
|
|
puts("data");
|
|
return 0;
|
|
}
|
|
|
|
|
|
/* usage */
|
|
static int _usage(void)
|
|
{
|
|
fputs("Usage: " PROGNAME " [-dh][-M file][-m file] file ...\n\
|
|
" PROGNAME " -i [-h] file ...\n", stderr);
|
|
return 1;
|
|
}
|
|
|
|
|
|
/* main */
|
|
int main(int argc, char * argv[])
|
|
{
|
|
Prefs p = 0;
|
|
int o;
|
|
|
|
while((o = getopt(argc, argv, "dhM:m:i")) != -1)
|
|
switch(o)
|
|
{
|
|
case 'd':
|
|
if(p & FILE_PREFS_i)
|
|
return _usage();
|
|
p |= FILE_PREFS_d;
|
|
break;
|
|
case 'h':
|
|
p |= FILE_PREFS_h;
|
|
break;
|
|
case 'i':
|
|
if(p != 0)
|
|
return _usage();
|
|
p = FILE_PREFS_i;
|
|
break;
|
|
case 'M':
|
|
if(p & FILE_PREFS_i)
|
|
return _usage();
|
|
p |= FILE_PREFS_M;
|
|
break;
|
|
case 'm':
|
|
if(p & FILE_PREFS_i)
|
|
return _usage();
|
|
p |= FILE_PREFS_m;
|
|
break;
|
|
default:
|
|
return _usage();
|
|
}
|
|
return _file(&p, argc - optind, &argv[optind]);
|
|
}
|