Commit 9a56205f authored by Enji Cooper's avatar Enji Cooper
Browse files

Add vendor import for pjdfstest

This vendor import code was obtained from
https://github.com/pjd/pjdfstest/commit/abf03c3a47745d4521b0e4aa141317553ca48f91

Approved by: rpaulo (mentor)
Phabric: D743
Sponsored by: EMC / Isilon Storage Division
parents
$FreeBSD: head/tools/regression/pjdfstest/LICENSE 211354 2010-08-15 21:29:03Z pjd $
License for all regression tests available with pjdfstest:
Copyright (c) 2006-2012 Pawel Jakub Dawidek <pawel@dawidek.net>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
# $FreeBSD$
PROG= pjdfstest
${PROG}: ${PROG}.c
@OSTYPE=`uname`; \
CFLAGS=-D__OS_$${OSTYPE}__; \
if [ $$OSTYPE = "FreeBSD" ]; then \
CFLAGS="$$CFLAGS -DHAS_LCHMOD -DHAS_CHFLAGS -DHAS_FCHFLAGS -DHAS_CHFLAGSAT -DHAS_LCHFLAGS -DHAS_FREEBSD_ACL -DHAS_BINDAT -DHAS_CONNECTAT -DHAS_LPATHCONF"; \
elif [ $$OSTYPE = "SunOS" ]; then \
CFLAGS="$$CFLAGS -DHAS_TRUNCATE64 -DHAS_STAT64"; \
CFLAGS="$$CFLAGS -lsocket"; \
elif [ $$OSTYPE = "Darwin" ]; then \
CFLAGS="$$CFLAGS -DHAS_LCHMOD -DHAS_CHFLAGS -DHAS_LCHFLAGS"; \
elif [ $$OSTYPE == "Linux" ]; then \
CFLAGS="$$CFLAGS -D_GNU_SOURCE"; \
else \
echo "Unsupported operating system: ${OSTYPE}."; \
exit 1; \
fi; \
cmd="gcc -Wall $$CFLAGS ${PROG}.c -o ${PROG}"; \
echo $$cmd; \
$$cmd
clean:
rm -f ${PROG}
$FreeBSD: head/tools/regression/pjdfstest/README 211354 2010-08-15 21:29:03Z pjd $
Few notes on how to use pjdfstest in short steps:
# cd pjdfstest
# vi tests/conf
Change 'fs' to file system type you want to test (UFS or ZFS).
# vi Makefile
You need to manually tweak few things by editing CFLAGS lines
at the top of the file.
# make
It will compile pjdfstest utility which is used by regression tests.
# cd /path/to/file/system/you/want/to/test/
# prove -r /path/to/pjdfstest/tests
That's all. Enjoy.
Currently supported operating systems: FreeBSD, Solaris.
Currently supported file system types: UFS, ZFS.
--
Pawel Jakub Dawidek <pawel@dawidek.net>
/*-
* Copyright (c) 2006-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#ifndef makedev
#include <sys/mkdev.h>
#endif
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <grp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifndef HAS_TRUNCATE64
#define truncate64 truncate
#define ftruncate64 ftruncate
#endif
#ifndef HAS_STAT64
#define stat64 stat
#define fstat64 fstat
#define lstat64 lstat
#endif
#ifdef HAS_FREEBSD_ACL
#include <sys/acl.h>
#endif
#ifndef ALLPERMS
#define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
#endif
enum action {
ACTION_OPEN,
ACTION_OPENAT,
ACTION_CREATE,
ACTION_UNLINK,
ACTION_UNLINKAT,
ACTION_MKDIR,
ACTION_MKDIRAT,
ACTION_RMDIR,
ACTION_LINK,
ACTION_LINKAT,
ACTION_SYMLINK,
ACTION_SYMLINKAT,
ACTION_RENAME,
ACTION_RENAMEAT,
ACTION_MKFIFO,
ACTION_MKFIFOAT,
ACTION_MKNOD,
ACTION_MKNODAT,
ACTION_BIND,
#ifdef HAS_BINDAT
ACTION_BINDAT,
#endif
ACTION_CONNECT,
#ifdef HAS_CONNECTAT
ACTION_CONNECTAT,
#endif
ACTION_CHMOD,
ACTION_FCHMOD,
#ifdef HAS_LCHMOD
ACTION_LCHMOD,
#endif
ACTION_FCHMODAT,
ACTION_CHOWN,
ACTION_FCHOWN,
ACTION_LCHOWN,
ACTION_FCHOWNAT,
#ifdef HAS_CHFLAGS
ACTION_CHFLAGS,
#endif
#ifdef HAS_FCHFLAGS
ACTION_FCHFLAGS,
#endif
#ifdef HAS_CHFLAGSAT
ACTION_CHFLAGSAT,
#endif
#ifdef HAS_LCHFLAGS
ACTION_LCHFLAGS,
#endif
ACTION_TRUNCATE,
ACTION_FTRUNCATE,
ACTION_STAT,
ACTION_FSTAT,
ACTION_LSTAT,
ACTION_FSTATAT,
ACTION_PATHCONF,
ACTION_FPATHCONF,
#ifdef HAS_LPATHCONF
ACTION_LPATHCONF,
#endif
#ifdef HAS_FREEBSD_ACL
ACTION_PREPENDACL,
ACTION_READACL,
#endif
ACTION_WRITE,
};
#define TYPE_NONE 0x0000
#define TYPE_STRING 0x0001
#define TYPE_NUMBER 0x0002
#define TYPE_DESCRIPTOR 0x0003
#define TYPE_MASK 0x000f
#define TYPE_OPTIONAL 0x0100
#define MAX_ARGS 8
struct syscall_desc {
const char *sd_name;
enum action sd_action;
int sd_args[MAX_ARGS];
};
static struct syscall_desc syscalls[] = {
{ "open", ACTION_OPEN, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } },
{ "openat", ACTION_OPENAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER | TYPE_OPTIONAL, TYPE_NONE } },
{ "create", ACTION_CREATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
{ "unlink", ACTION_UNLINK, { TYPE_STRING, TYPE_NONE } },
{ "unlinkat", ACTION_UNLINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
{ "mkdir", ACTION_MKDIR, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
{ "mkdirat", ACTION_MKDIRAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
{ "rmdir", ACTION_RMDIR, { TYPE_STRING, TYPE_NONE } },
{ "link", ACTION_LINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
{ "linkat", ACTION_LINKAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
{ "symlink", ACTION_SYMLINK, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
{ "symlinkat", ACTION_SYMLINKAT, { TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
{ "rename", ACTION_RENAME, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
{ "renameat", ACTION_RENAMEAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
{ "mkfifo", ACTION_MKFIFO, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
{ "mkfifoat", ACTION_MKFIFOAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
{ "mknod", ACTION_MKNOD, { TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} },
{ "mknodat", ACTION_MKNODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE} },
{ "bind", ACTION_BIND, { TYPE_STRING, TYPE_NONE } },
#ifdef HAS_BINDAT
{ "bindat", ACTION_BINDAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
#endif
{ "connect", ACTION_CONNECT, { TYPE_STRING, TYPE_NONE } },
#ifdef HAS_CONNECTAT
{ "connectat", ACTION_CONNECTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
#endif
{ "chmod", ACTION_CHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
{ "fchmod", ACTION_FCHMOD, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } },
#ifdef HAS_LCHMOD
{ "lchmod", ACTION_LCHMOD, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
#endif
{ "fchmodat", ACTION_FCHMODAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } },
{ "chown", ACTION_CHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
{ "fchown", ACTION_FCHOWN, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
{ "lchown", ACTION_LCHOWN, { TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_NONE } },
{ "fchownat", ACTION_FCHOWNAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NUMBER, TYPE_NUMBER, TYPE_STRING, TYPE_NONE } },
#ifdef HAS_CHFLAGS
{ "chflags", ACTION_CHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
#endif
#ifdef HAS_FCHFLAGS
{ "fchflags", ACTION_FCHFLAGS, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
#endif
#ifdef HAS_CHFLAGSAT
{ "chflagsat", ACTION_CHFLAGSAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
#endif
#ifdef HAS_LCHFLAGS
{ "lchflags", ACTION_LCHFLAGS, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
#endif
{ "truncate", ACTION_TRUNCATE, { TYPE_STRING, TYPE_NUMBER, TYPE_NONE } },
{ "ftruncate", ACTION_FTRUNCATE, { TYPE_DESCRIPTOR, TYPE_NUMBER, TYPE_NONE } },
{ "stat", ACTION_STAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
{ "fstat", ACTION_FSTAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
{ "lstat", ACTION_LSTAT, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
{ "fstatat", ACTION_FSTATAT, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_STRING, TYPE_STRING, TYPE_NONE } },
{ "pathconf", ACTION_PATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
{ "fpathconf", ACTION_FPATHCONF, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
#ifdef HAS_LPATHCONF
{ "lpathconf", ACTION_LPATHCONF, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
#endif
#ifdef HAS_FREEBSD_ACL
{ "prependacl", ACTION_PREPENDACL, { TYPE_STRING, TYPE_STRING, TYPE_NONE } },
{ "readacl", ACTION_READACL, { TYPE_STRING, TYPE_NONE } },
#endif
{ "write", ACTION_WRITE, { TYPE_DESCRIPTOR, TYPE_STRING, TYPE_NONE } },
{ NULL, -1, { TYPE_NONE } }
};
struct flag {
long long f_flag;
const char *f_str;
};
static struct flag open_flags[] = {
#ifdef O_RDONLY
{ O_RDONLY, "O_RDONLY" },
#endif
#ifdef O_WRONLY
{ O_WRONLY, "O_WRONLY" },
#endif
#ifdef O_RDWR
{ O_RDWR, "O_RDWR" },
#endif
#ifdef O_NONBLOCK
{ O_NONBLOCK, "O_NONBLOCK" },
#endif
#ifdef O_APPEND
{ O_APPEND, "O_APPEND" },
#endif
#ifdef O_CREAT
{ O_CREAT, "O_CREAT" },
#endif
#ifdef O_TRUNC
{ O_TRUNC, "O_TRUNC" },
#endif
#ifdef O_EXCL
{ O_EXCL, "O_EXCL" },
#endif
#ifdef O_SHLOCK
{ O_SHLOCK, "O_SHLOCK" },
#endif
#ifdef O_EXLOCK
{ O_EXLOCK, "O_EXLOCK" },
#endif
#ifdef O_DIRECT
{ O_DIRECT, "O_DIRECT" },
#endif
#ifdef O_FSYNC
{ O_FSYNC, "O_FSYNC" },
#endif
#ifdef O_SYNC
{ O_SYNC, "O_SYNC" },
#endif
#ifdef O_NOFOLLOW
{ O_NOFOLLOW, "O_NOFOLLOW" },
#endif
#ifdef O_NOCTTY
{ O_NOCTTY, "O_NOCTTY" },
#endif
#ifdef O_DIRECTORY
{ O_DIRECTORY, "O_DIRECTORY" },
#endif
{ 0, NULL }
};
#ifdef HAS_CHFLAGS
static struct flag chflags_flags[] = {
#ifdef UF_NODUMP
{ UF_NODUMP, "UF_NODUMP" },
#endif
#ifdef UF_IMMUTABLE
{ UF_IMMUTABLE, "UF_IMMUTABLE" },
#endif
#ifdef UF_APPEND
{ UF_APPEND, "UF_APPEND" },
#endif
#ifdef UF_NOUNLINK
{ UF_NOUNLINK, "UF_NOUNLINK" },
#endif
#ifdef UF_OPAQUE
{ UF_OPAQUE, "UF_OPAQUE" },
#endif
#ifdef SF_ARCHIVED
{ SF_ARCHIVED, "SF_ARCHIVED" },
#endif
#ifdef SF_IMMUTABLE
{ SF_IMMUTABLE, "SF_IMMUTABLE" },
#endif
#ifdef SF_APPEND
{ SF_APPEND, "SF_APPEND" },
#endif
#ifdef SF_NOUNLINK
{ SF_NOUNLINK, "SF_NOUNLINK" },
#endif
#ifdef SF_SNAPSHOT
{ SF_SNAPSHOT, "SF_SNAPSHOT" },
#endif
{ 0, NULL }
};
#endif
static struct flag unlinkat_flags[] = {
{ AT_REMOVEDIR, "AT_REMOVEDIR" },
{ 0, NULL }
};
static struct flag linkat_flags[] = {
{ AT_SYMLINK_FOLLOW, "AT_SYMLINK_FOLLOW" },
{ 0, NULL }
};
static struct flag chflagsat_flags[] = {
{ AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
{ 0, NULL }
};
static struct flag fchmodat_flags[] = {
{ AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
{ 0, NULL }
};
static struct flag fchownat_flags[] = {
{ AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
{ 0, NULL }
};
static struct flag fstatat_flags[] = {
{ AT_SYMLINK_NOFOLLOW, "AT_SYMLINK_NOFOLLOW" },
{ 0, NULL }
};
struct name {
int n_name;
const char *n_str;
};
static struct name pathconf_names[] = {
#ifdef _PC_LINK_MAX
{ _PC_LINK_MAX, "_PC_LINK_MAX" },
#endif
#ifdef _PC_NAME_MAX
{ _PC_NAME_MAX, "_PC_NAME_MAX" },
#endif
#ifdef _PC_PATH_MAX
{ _PC_PATH_MAX, "_PC_PATH_MAX" },
#endif
#ifdef _PC_SYMLINK_MAX
{ _PC_SYMLINK_MAX, "_PC_SYMLINK_MAX" },
#endif
{ 0, NULL }
};
static const char *err2str(int error);
static int *descriptors;
static int ndescriptors;
static void
usage(void)
{
fprintf(stderr, "usage: pjdfstest [-U umask] [-u uid] [-g gid1[,gid2[...]]] syscall args ...\n");
exit(1);
}
static long long
str2flags(struct flag *tflags, char *sflags)
{
long long flags = 0;
unsigned int i;
char *f;
/* 'none' or '0' means no flags */
if (strcmp(sflags, "none") == 0 || strcmp(sflags, "0") == 0)
return (0);
for (f = strtok(sflags, ",|"); f != NULL; f = strtok(NULL, ",|")) {
for (i = 0; tflags[i].f_str != NULL; i++) {
if (strcmp(tflags[i].f_str, f) == 0)
break;
}
if (tflags[i].f_str == NULL) {
fprintf(stderr, "unknown flag '%s'\n", f);
exit(1);
}
flags |= tflags[i].f_flag;
}
return (flags);
}
#ifdef HAS_CHFLAGS
static char *
flags2str(struct flag *tflags, long long flags)
{
static char sflags[1024];
unsigned int i;
sflags[0] = '\0';
for (i = 0; tflags[i].f_str != NULL; i++) {
if (flags & tflags[i].f_flag) {
if (sflags[0] != '\0')
strlcat(sflags, ",", sizeof(sflags));
strlcat(sflags, tflags[i].f_str, sizeof(sflags));
}
}
if (sflags[0] == '\0')
strlcpy(sflags, "none", sizeof(sflags));
return (sflags);
}
#endif
static int
str2name(struct name *names, char *name)
{
unsigned int i;
for (i = 0; names[i].n_str != NULL; i++) {
if (strcmp(names[i].n_str, name) == 0)
return (names[i].n_name);
}
return (-1);
}
static struct syscall_desc *
find_syscall(const char *name)
{
int i;
for (i = 0; syscalls[i].sd_name != NULL; i++) {
if (strcmp(syscalls[i].sd_name, name) == 0)
return (&syscalls[i]);
}
return (NULL);
}
static void
show_stat(struct stat64 *sp, const char *what)
{
if (strcmp(what, "mode") == 0)
printf("0%o", (unsigned int)(sp->st_mode & ALLPERMS));
else if (strcmp(what, "inode") == 0)
printf("%lld", (long long)sp->st_ino);
else if (strcmp(what, "nlink") == 0)
printf("%lld", (long long)sp->st_nlink);
else if (strcmp(what, "uid") == 0)
printf("%d", (int)sp->st_uid);
else if (strcmp(what, "gid") == 0)
printf("%d", (int)sp->st_gid);
else if (strcmp(what, "size") == 0)
printf("%lld", (long long)sp->st_size);
else if (strcmp(what, "blocks") == 0)
printf("%lld", (long long)sp->st_blocks);
else if (strcmp(what, "atime") == 0)
printf("%lld", (long long)sp->st_atime);
else if (strcmp(what, "mtime") == 0)
printf("%lld", (long long)sp->st_mtime);
else if (strcmp(what, "ctime") == 0)
printf("%lld", (long long)sp->st_ctime);
#ifdef HAS_CHFLAGS
else if (strcmp(what, "flags") == 0)
printf("%s", flags2str(chflags_flags, (long long)sp->st_flags));
#endif
else if (strcmp(what, "major") == 0)
printf("%u", (unsigned int)major(sp->st_rdev));
else if (strcmp(what, "minor") == 0)
printf("%u", (unsigned int)minor(sp->st_rdev));
else if (strcmp(what, "type") == 0) {
switch (sp->st_mode & S_IFMT) {
case S_IFIFO:
printf("fifo");
break;
case S_IFCHR:
printf("char");
break;
case S_IFDIR:
printf("dir");
break;
case S_IFBLK:
printf("block");
break;
case S_IFREG:
printf("regular");
break;
case S_IFLNK:
printf("symlink");
break;
case S_IFSOCK:
printf("socket");
break;
default:
printf("unknown");
break;
}
} else {
printf("unknown");
}
}
static void
show_stats(struct stat64 *sp, char *what)
{
const char *s = "";
char *w;
for (w = strtok(what, ","); w != NULL; w = strtok(NULL, ",")) {
printf("%s", s);
show_stat(sp, w);
s = ",";
}
printf("\n");
}
static void
descriptor_add(int fd)
{
ndescriptors++;
if (descriptors == NULL) {
descriptors = malloc(sizeof(descriptors[0]) * ndescriptors);
} else {
descriptors = realloc(descriptors,
sizeof(descriptors[0]) * ndescriptors);
}
assert(descriptors != NULL);
descriptors[ndescriptors - 1] = fd;
}
static int
descriptor_get(int pos)
{
if (pos < 0 || pos >= ndescriptors) {
fprintf(stderr, "invalid descriptor %d\n", pos);
exit(1);
}
return (descriptors[pos]);
}
static unsigned int
call_syscall