#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <limits.h>
#include <errno.h>
#include <utime.h>

#include "fop.h"

extern void *	nsfio_get_function(const char *);

#define IML_NSC_TYPE_DESKTOP 1

iml__nsc_create_t	nsfio__nsc_create;
iml__nsc_free_t		nsfio__nsc_free;

iml_nsc_open_t		nsfio_open;
iml_nsc_read_t		nsfio_read;
iml_nsc_readv_t		nsfio_readv;
iml_nsc_write_t		nsfio_write;
iml_nsc_writev_t	nsfio_writev;
iml_nsc_close_t		nsfio_close;
iml_nsc_creat_t		nsfio_creat;

iml_nsc_lseek_t		nsfio_lseek;

iml_nsc_stat_t		nsfio_stat;
iml_nsc_lstat_t		nsfio_lstat;
iml_nsc_fstat_t		nsfio_fstat;

iml_nsc_mkdir_t		nsfio_mkdir;
iml_nsc_rmdir_t		nsfio_rmdir;

iml_nsc_symlink_t	nsfio_symlink;
iml_nsc_readlink_t	nsfio_readlink;
iml_nsc_link_t		nsfio_link;
iml_nsc_unlink_t	nsfio_unlink;
iml_nsc_rename_t	nsfio_rename;

iml_nsc_fcntl_t		nsfio_fcntl;
iml_nsc_truncate_t	nsfio_truncate;
iml_nsc_ftruncate_t	nsfio_ftruncate;

iml_nsc_opendir_t	nsfio_opendir;
iml_nsc_readdir_t	nsfio_readdir;
iml_nsc_closedir_t	nsfio_closedir;

iml_nsc_access_t	nsfio_access;
iml_nsc_chmod_t		nsfio_chmod;
iml_nsc_fchmod_t	nsfio_fchmod;
iml_nsc_chown_t		nsfio_chown;
#if 0
iml_nsc_lchown_t	nsfio_lchown;
#endif /* 0 */
iml_nsc_fchown_t	nsfio_fchown;
iml_nsc_fpathconf_t	nsfio_fpathconf;
iml_nsc_pathconf_t	nsfio_pathconf;
iml_nsc_utime_t		nsfio_utime;
iml_nsc_utimes_t	nsfio_utimes;

#define BASEDIR	"/var/lib/iiim/le/test/dir"

#define TEST_FILE1	"/var/lib/iiim/le/test/dir/test_file1"
#define TEST_FILE2	"/var/lib/iiim/le/test/dir/test_file2"
#define TEST_SYMLINK	"test_file1"

#define TEST_DIR_FILE1	"/var/lib/iiim/le/test/dir/test_dir1/fiiiileeee1"
#define TEST_DIR_FILE2	"/var/lib/iiim/le/test/dir/test_dir1/f2"

#define TEST_DIR1	"/var/lib/iiim/le/test/dir/test_dir1"
#define ABC		"abcdefghijklmnopqrstuvwxyz"

#if !defined(S_IAMB)
#define S_IAMB	0x1FF
#endif /* !S_IAMB */


void
test_prep(nsfio_t * nsc)
{
    DIR *		dirp;
    struct dirent *	de;
    struct stat		st;
    char		path[PATH_MAX];

    umask(0);

    nsfio_mkdir(nsc, BASEDIR, 0777);
    dirp = nsfio_opendir(nsc, BASEDIR);
    while (NULL != (de = nsfio_readdir(nsc, dirp))) {
	if ((0 == strcmp(".", de->d_name)) ||
	    (0 == strcmp("..", de->d_name))) {
	    continue;
	}
	snprintf(path, sizeof (path), "%s/%s", BASEDIR, de->d_name);
	nsfio_stat(nsc, path, &st);
	if (0 == S_ISDIR(st.st_mode)) {
	    nsfio_unlink(nsc, path);
	} else {
	    nsfio_rmdir(nsc, path);
	}
   }
}


void
test_open(nsfio_t * nsc)
{
    int		fd;
    struct stat	st;

    printf("open: ");
    fd = nsfio_open(nsc, TEST_FILE1, O_RDWR);
    if (0 <= fd) {
	printf("fail: open should fail\n");
	nsfio_close(nsc, fd);
	return;
    }

    fd = nsfio_open(nsc, TEST_FILE1, O_RDWR | O_CREAT | O_TRUNC, 0612);
    if (fd < 0) {
	printf("fail: open should succeed\n");
	return;
    }
    nsfio_close(nsc, fd);

    if (nsfio_stat(nsc, TEST_FILE1, &st) < 0) {
	printf("fail: %s does not exist\n", TEST_FILE1);
	return;
    } else {
	if (0612 != (S_IAMB & st.st_mode)) {
	    printf("fail: mode error: 0%3o\n", (S_IAMB & st.st_mode));
	    return;
	}
    }

    fd = nsfio_open(nsc, TEST_FILE1, O_RDWR);
    if (fd < 0) {
	printf("fail: open should succeed (o_RDWR)\n");
	return;
    }
    nsfio_close(nsc, fd);

    printf("succeed\n");
}


void
test_read(nsfio_t * nsc)
{
    char	buf[1024];
    int		fd;
    int		rv;

    printf("read: ");

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0777);
    nsfio_write(nsc, fd, "hogera", 7);
    nsfio_close(nsc, fd);

    memset(buf, 0, sizeof (buf));
    fd = nsfio_open(nsc, TEST_FILE1, O_RDONLY);
    rv = nsfio_read(nsc, fd, buf, sizeof (buf));
    nsfio_close(nsc, fd);

    if (7 != rv) {
	printf("fail - read length error\n");
	return;
    }

    if (0 != memcmp(buf, "hogera", 7)) {
	printf("fail - incorrect contents\n");
	return;
    }

    printf("succeed\n");
}


void
test_readv(nsfio_t * nsc)
{
    printf("readv: ");
    printf("succeed\n");
}


void
test_write(nsfio_t * nsc)
{
    char	buf[1024];
    int		fd;
    int		rv;

    printf("write: ");

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0777);

    rv = nsfio_write(nsc, fd, "hogera", 7);
    nsfio_close(nsc, fd);
    if (7 != rv) {
	printf("fail - write length error\n");
	return;
    }


    memset(buf, 0, sizeof (buf));
    fd = nsfio_open(nsc, TEST_FILE1, O_RDONLY);
    rv = nsfio_read(nsc, fd, buf, sizeof (buf));
    nsfio_close(nsc, fd);

    if (0 != memcmp(buf, "hogera", 7)) {
	printf("fail - incorrect contents\n");
	return;
    }

     printf("succeed\n");
}


void
test_writev(nsfio_t * nsc)
{
    printf("writev: ");
    printf("succeed\n");
}


void
test_close(nsfio_t * nsc)
{
    int	fd;
    int	rv;

    printf("close: ");

    fd = nsfio_open(nsc, TEST_FILE1, O_RDWR | O_CREAT | O_TRUNC, 0777);

    rv = nsfio_close(nsc, fd);
    if (rv < 0) {
	printf("fail - close error");
	return;
    }

    fd = nsfio_open(nsc, TEST_FILE1, O_RDWR | O_CREAT | O_TRUNC, 0777);

    rv = nsfio_close(nsc, fd + 5);
    (void)nsfio_close(nsc, fd);
    if (0 <= rv) {
	printf("fail - close should fail");
	return;
    }

    printf("succeed\n");
}


void
test_creat(nsfio_t * nsc)
{
    int		fd;
    struct stat	st;

    printf("creat: ");

    if (0 == nsfio_stat(nsc, TEST_FILE1, &st)) {
	nsfio_unlink(nsc, TEST_FILE1);
	if (0 == nsfio_stat(nsc, TEST_FILE1, &st)) {
	    printf("fail: can not remove %s\n", TEST_FILE1);
	    return;
	}
    }

    fd = nsfio_creat(nsc, TEST_FILE1, 0700);
    if (fd < 0) {
	printf("fail: open should succeed\n");
	return;
    }

    if (nsfio_stat(nsc, TEST_FILE1, &st) < 0) {
	printf("fail: %s does not exist\n", TEST_FILE1);
	return;
    } else {
	if (0700 != (S_IAMB & st.st_mode)) {
	    printf("fail: mode error: %04o\n", st.st_mode);
	    return;
	}
    }

    nsfio_unlink(nsc, TEST_FILE1);

    printf("succeed\n");
}


void
test_lseek(nsfio_t * nsc)
{
    int		fd;
    char	buf[26];

    printf("lseek: ");

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0666);
    nsfio_write(nsc, fd, ABC, 26);
    nsfio_close(nsc, fd);

    fd = nsfio_open(nsc, TEST_FILE1, O_RDONLY);
    nsfio_lseek(nsc, fd, 3, SEEK_SET);
    nsfio_read(nsc, fd, buf, 1);
    if ('d' != buf[0]) {
	printf("fail: SEEK_SET not working\n");
	return;
    }
    nsfio_lseek(nsc, fd, 3, SEEK_CUR);
    nsfio_read(nsc, fd, buf, 1);
    if ('h' != buf[0]) {
	printf("fail: SEEK_CUR not working\n");
	return;
    }
    nsfio_lseek(nsc, fd, -3, SEEK_END);
    nsfio_read(nsc, fd, buf, 1);
    if ('x' != buf[0]) {
	printf("fail: SEEK_END not working\n");
	return;
    }

    nsfio_close(nsc, fd);
    nsfio_unlink(nsc, TEST_FILE1);

    printf("succeed\n");
}


void
test_stat(nsfio_t * nsc)
{
    int		fd;
    struct stat	st;

    printf("stat: ");

    if (0 == nsfio_stat(nsc, TEST_FILE1, &st)) {
	printf("fail: stat should fail on none-existent file\n");
	return;
    }

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    nsfio_write(nsc, fd, "data", 4);
    nsfio_close(nsc, fd);

    if (0 != nsfio_stat(nsc, TEST_FILE1, &st)) {
	printf("fail: stat should succeed\n");
	return;
    }

    if ((0655 != (S_IAMB & st.st_mode)) || (geteuid() != st.st_uid) || (4 != st.st_size)) {
	printf("fail: (0655 != %d) || (geteuid() != %d) || (4 != %lu))\n",
	       st.st_mode, st.st_uid, (unsigned long)st.st_size);
	return;
    }
    
    nsfio_unlink(nsc, TEST_FILE1);
    printf("succeed\n");
}


void
test_lstat(nsfio_t * nsc)
{
    int		fd;
    struct stat	st;

    printf("lstat: ");

    if (0 == nsfio_lstat(nsc, TEST_FILE1, &st)) {
	printf("fail: lstat should fail on none-existent file\n");
	return;
    }

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    nsfio_write(nsc, fd, "data", 4);
    nsfio_close(nsc, fd);

    if (0 != nsfio_lstat(nsc, TEST_FILE1, &st)) {
	printf("fail: lstat should succeed\n");
	return;
    }

    if ((0655 != (S_IAMB & st.st_mode)) ||
	(geteuid() != st.st_uid) ||
	(4 != st.st_size)) {
	printf("fail: (0655 != %d) || (geteuid() != %d) || (4 != %lu))\n",
	       (S_IAMB & st.st_mode), st.st_uid, (unsigned long)st.st_size);
	return;
    }
    
    nsfio_unlink(nsc, TEST_FILE1);
    printf("succeed\n");
}


void
test_fstat(nsfio_t * nsc)
{
    int		fd;
    struct stat	st;
    int		rv;

    printf("fstat: ");

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    nsfio_write(nsc, fd, "data", 4);

    rv = nsfio_fstat(nsc, fd, &st);
    nsfio_close(nsc, fd);
    nsfio_unlink(nsc, TEST_FILE1);

    if (0 != rv) {
	printf("fail: fstat should succeed\n");
	return;
    }

    if ((0655 != (S_IAMB & st.st_mode)) ||
	(geteuid() != st.st_uid) ||
	(4 != st.st_size)) {
	printf("fail: (0655 != %d) || (geteuid() != %d) || (4 != %lu))\n",
	       (S_IAMB & st.st_mode), st.st_uid, (unsigned long)st.st_size);
	return;
    }
    
    printf("succeed\n");
}


void
test_mkkdir(nsfio_t * nsc)
{
    struct stat	st;

    printf("mkkdir: ");

    if (0 == nsfio_stat(nsc, TEST_DIR1, &st)) {
	nsfio_rmdir(nsc, TEST_DIR1);
    }

    nsfio_mkdir(nsc, TEST_DIR1, 0711);
    nsfio_stat(nsc, TEST_DIR1, &st);
    nsfio_rmdir(nsc, TEST_DIR1);

    if (0 == S_ISDIR(st.st_mode)) {
	printf("fail: not a directory\n");
	return;
    } else if (0711 != (S_IAMB & st.st_mode)) {
	printf("fail: incorrect permission: %04o\n", (S_IAMB & st.st_mode));
	return;
    } else if (getuid() != st.st_uid) {
	printf("fail: incorrect uid: %d\n", st.st_uid);
	return;
    }

    printf("succeed\n");
}


void
test_rmdir(nsfio_t * nsc)
{
    int		rv;
    struct stat	st;

    printf("rmdir: ");

    rv = nsfio_rmdir(nsc, TEST_DIR1);
    if (0 == rv) {
	printf("fail: rmdir should fail on non-existent directory\n");
	return;
    } else if (ENOENT != errno) {
	printf("fail: errno should be ENOENT\n");
	return;
    }

    nsfio_mkdir(nsc, TEST_DIR1, 0711);
    rv = nsfio_rmdir(nsc, TEST_DIR1);
    if (rv < 0) {
	printf("fail: errno should succeed\n");
	return;
    }
    if (0 == nsfio_stat(nsc, TEST_DIR1, &st)) {
	printf("fail: %s exists\n", TEST_DIR1);
	return;
    }

    printf("succeed\n");
}


void
test_symlink(nsfio_t * nsc)
{
    int		fd;
    struct stat	st;

    printf("symlink: ");

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    nsfio_close(nsc, fd);

    if (0 != nsfio_symlink(nsc, TEST_SYMLINK, TEST_FILE2)) {
	printf("fail: symlink failed\n");
	nsfio_unlink(nsc, TEST_FILE1);
	return;
    }

    if (0 != nsfio_stat(nsc, TEST_FILE2, &st)) {
	printf("fail: stat on %s\n", TEST_FILE2);
    } else if (0 != nsfio_lstat(nsc, TEST_FILE2, &st)) {
	printf("fail: lstat on %s\n", TEST_FILE2);
    } else if (0 == S_ISLNK(st.st_mode)) {
	printf("fail: %s is not a symbolic link\n", TEST_FILE2);
    } else {
	printf("succeed\n");
    }

    nsfio_unlink(nsc, TEST_FILE1);
    nsfio_unlink(nsc, TEST_FILE2);
}


void
test_readink(nsfio_t * nsc)
{
    int		rv;
    char	buf[1024];

    printf("readlink: ");

    if (0 != nsfio_symlink(nsc, "symbolic link", TEST_FILE1)) {
	printf("fail: symlink failed\n");
	return;
    }

    rv = nsfio_readlink(nsc, TEST_FILE1, buf, sizeof (buf));
    nsfio_unlink(nsc, TEST_FILE1);

    if (0 < rv) {
	printf("fail: readlink failed\n");
    } else if (0 != strcmp("symlink link", buf)) {
	printf("fail: contents error \"%s\" != \"%s\"\n", "symlink link", buf);
    }

    return;
}


void
test_link(nsfio_t * nsc)
{
    int		fd;
    int		rv;
    struct stat	st;

    printf("link: ");

    rv = nsfio_link(nsc, TEST_FILE1, TEST_FILE2);
    if (0 == rv) {
	printf("error: link should fail\n");
	return;
    }

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    nsfio_close(nsc, fd);

    rv = nsfio_link(nsc, TEST_FILE1, TEST_FILE2);
    if (0 != rv) {
	printf("error: link should succeed\n");
	return;
    }

    nsfio_unlink(nsc, TEST_FILE1);

    if (0 != nsfio_stat(nsc, TEST_FILE2, &st)) {
	printf("fail: stat on %s\n", TEST_FILE2);
    } else {
	printf("succeed\n");
    }

    nsfio_unlink(nsc, TEST_FILE2);
}


void
test_unlink(nsfio_t * nsc)
{
    int		fd;
    int		rv;

    printf("unlink: ");

    rv = nsfio_unlink(nsc, TEST_FILE1);
    if (0 == rv) {
	printf("error: unlink should fail\n");
	return;
    } else if (ENOENT != errno) {
	printf("error: errno should be ENOENT\n");
    }

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    nsfio_close(nsc, fd);

    rv = nsfio_unlink(nsc, TEST_FILE1);
    if (0 != rv) {
	printf("error: unlink should succeed\n");
	return;
    }

    printf("succeed\n");
}


void
test_rename(nsfio_t * nsc)
{
    int		fd;
    int		rv;
    struct stat	st;

    printf("rename: ");

    rv = nsfio_rename(nsc, TEST_FILE1, TEST_FILE2);
    if (0 == rv) {
	printf("error: rename should fail\n");
	return;
    }

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    nsfio_close(nsc, fd);

    rv = nsfio_rename(nsc, TEST_FILE1, TEST_FILE2);
    if (0 != rv) {
	printf("error: rename should succeed\n");
	return;
    }

    if (0 == nsfio_stat(nsc, TEST_FILE1, &st)) {
	printf("fail: stat on \"%s\" should fail\n", TEST_FILE1);
    } else if (0 != nsfio_stat(nsc, TEST_FILE2, &st)) {
	printf("fail: stat on \"%s\" should succeed\n", TEST_FILE2);
    } else {
	printf("succeed\n");
    }

    nsfio_unlink(nsc, TEST_FILE1);
    nsfio_unlink(nsc, TEST_FILE2);
}


void
test_fcntl(nsfio_t * nsc)
{
    int		fd;
    int		rv;

    printf("fcntl: ");

    rv = nsfio_fcntl(nsc, 99, F_GETFD);
    if (0 <= rv) {
	printf("error: fcntl on invalid fd should fail\n");
	return;
    }

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);

    nsfio_fcntl(nsc, fd, F_SETFD, FD_CLOEXEC);
    rv = nsfio_fcntl(nsc, fd, F_GETFD);
    if (rv < 0) {
	printf("error: fcntl should succeed\n");
    } else if (FD_CLOEXEC != rv) {
	printf("error: invalid flags 0x%x\n", rv);
    } else {
	printf("succeed\n");
    }

    nsfio_close(nsc, fd);
    nsfio_unlink(nsc, TEST_FILE1);
}


void
test_truncate(nsfio_t * nsc)
{
    int		fd;
    struct stat	st;
    int		rv;

    printf("truncate: ");

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);

    nsfio_write(nsc, fd, ABC, 26);
    nsfio_close(nsc, fd);

    rv = nsfio_truncate(nsc, TEST_FILE1, 16);
    if (0 != rv) {
	printf("fail: truncate should succeed\n");
    } else if (0 != nsfio_stat(nsc, TEST_FILE1, &st)) {
	printf("fail: stat error on %s\n", TEST_FILE1);
	if (16 != st.st_size) {
	    printf("fail: size not turncated %lu\n", (unsigned long)st.st_size);
	} else {
	    printf("succeed\n");
	}
    } else {
	printf("succeed\n");
    }

    nsfio_unlink(nsc, TEST_FILE1);
}


void
test_ftruncate(nsfio_t * nsc)
{
    int		fd;
    struct stat	st;
    int		rv;

    printf("ftruncate: ");

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);

    nsfio_write(nsc, fd, ABC, 26);

    rv = nsfio_ftruncate(nsc, fd, 16);
    nsfio_close(nsc, fd);

    if (0 != rv) {
	printf("fail: truncate should succeed\n");
    } else if (0 != nsfio_stat(nsc, TEST_FILE1, &st)) {
	printf("fail: stat error on %s\n", TEST_FILE1);
	if (16 != st.st_size) {
	    printf("fail: size not truncated %lu\n", (unsigned long)st.st_size);
	} else {
	    printf("succeed\n");
	}
    } else {
	printf("succeed\n");
    }

    nsfio_unlink(nsc, TEST_FILE1);
}


void
test_opendir(nsfio_t * nsc)
{
    int			fd;
    DIR *		dirp;
    struct dirent *	de;
    char		path[PATH_MAX];
    int			found1;
    int			found2;

    printf("opendir: ");

    nsfio_mkdir(nsc, TEST_DIR1, 0777);
    fd = nsfio_open(nsc, TEST_DIR_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    nsfio_close(nsc, fd);
    fd = nsfio_open(nsc, TEST_DIR_FILE2, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    nsfio_close(nsc, fd);
    found1 = 0;
    found2 = 0;

    dirp = nsfio_opendir(nsc, TEST_DIR1);
    while (NULL != (de = nsfio_readdir(nsc, dirp))) {
	if ((0 == strcmp(".", de->d_name)) ||
	    (0 == strcmp("..", de->d_name))) {
	    continue;
	}
	snprintf(path, sizeof (path), "%s/%s", TEST_DIR1, de->d_name);
	if (0 == strcmp(path, TEST_DIR_FILE1)) {
	    found1 = 1;
	} else if (0 == strcmp(path, TEST_DIR_FILE2)) {
	    found2 = 1;
	}
    }
    nsfio_closedir(nsc, dirp);

    if ((1 == found1) && (1 == found2)) {
	printf("succeed\n");
    } else {
	printf("fail: file not found\n");
    }

    nsfio_unlink(nsc, TEST_DIR_FILE1);
    nsfio_unlink(nsc, TEST_DIR_FILE2);
    nsfio_rmdir(nsc, TEST_DIR1);
}


void
test_readdir(nsfio_t * nsc)
{
    int			fd;
    DIR *		dirp;
    struct dirent *	de;
    char		path[PATH_MAX];
    int			found1;
    int			found2;

    printf("readdir: ");

    nsfio_mkdir(nsc, TEST_DIR1, 0777);
    fd = nsfio_open(nsc, TEST_DIR_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    nsfio_close(nsc, fd);
    fd = nsfio_open(nsc, TEST_DIR_FILE2, O_WRONLY | O_CREAT | O_TRUNC, 0655);
    nsfio_close(nsc, fd);
    found1 = 0;
    found2 = 0;

    dirp = nsfio_opendir(nsc, TEST_DIR1);
    while (NULL != (de = nsfio_readdir(nsc, dirp))) {
	if ((0 == strcmp(".", de->d_name)) ||
	    (0 == strcmp("..", de->d_name))) {
	    continue;
	}
	snprintf(path, sizeof (path), "%s/%s", TEST_DIR1, de->d_name);
	if (0 == strcmp(path, TEST_DIR_FILE1)) {
	    found1 = 1;
	} else if (0 == strcmp(path, TEST_DIR_FILE2)) {
	    found2 = 1;
	}
    }
    nsfio_closedir(nsc, dirp);

    if ((1 == found1) && (1 == found2)) {
	printf("succeed\n");
    } else {
	printf("fail: files not found\n");
    }

    nsfio_unlink(nsc, TEST_DIR_FILE1);
    nsfio_unlink(nsc, TEST_DIR_FILE2);
    nsfio_rmdir(nsc, TEST_DIR1);
}


void
test_closedir(nsfio_t * nsc)
{
    DIR *		dirp;

    printf("closedir: ");

    nsfio_mkdir(nsc, TEST_DIR1, 0777);

    dirp = nsfio_opendir(nsc, TEST_DIR1);
    if (0 == nsfio_closedir(nsc, dirp)) {
	printf("succeed\n");
    } else {
	printf("failed\n");
    }

    nsfio_rmdir(nsc, TEST_DIR1);
}


void
test_access(nsfio_t * nsc)
{
    int	rv;
    int	fd;

    printf("access: ");

    rv = nsfio_access(nsc, TEST_FILE1, F_OK);
    if (0 == rv) {
	printf("fail: F_OK should fail on none-existent file\n");
	return;
    }

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    nsfio_close(nsc, fd);

    if (0 != nsfio_access(nsc, TEST_FILE1, R_OK)) {
	printf("fail: R_OK should succeed\n");
    } else if (0 == nsfio_access(nsc, TEST_FILE1, X_OK)) {
	printf("fail: X_OK should fail\n");
    } else {
	printf("succeed\n");
    }

    nsfio_unlink(nsc, TEST_FILE1);
}


void
test_chmod(nsfio_t * nsc)
{
    int		rv;
    int		fd;
    struct stat	st;

    printf("chmod: ");

    rv = nsfio_chmod(nsc, TEST_FILE1, 0555);
    if (0 == rv) {
	printf("fail: should fail on none-existent file\n");
	return;
    }

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    nsfio_close(nsc, fd);

    if (0 != nsfio_chmod(nsc, TEST_FILE1, 0555)) {
	printf("fail: should succeed\n");
    } else {
	nsfio_stat(nsc, TEST_FILE1, &st);
	if (0555 != (S_IAMB & st.st_mode)) {
	    printf("fail: incorrect mode: %d\n", (S_IAMB & st.st_mode));
	} else {
	    printf("succeed\n");
	}
    }

    nsfio_unlink(nsc, TEST_FILE1);
}


void
test_fchmod(nsfio_t * nsc)
{
    int		rv;
    int		fd;
    struct stat	st;

    printf("fchmod: ");

    rv = nsfio_fchmod(nsc, 99, 0555);
    if (0 == rv) {
	printf("fail: should fail on none-existent file\n");
	return;
    }

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);

    if (0 != nsfio_fchmod(nsc, fd, 0555)) {
	printf("fail: should succeed\n");
    } else {
	nsfio_fstat(nsc, fd, &st);
	if (0555 != (S_IAMB & st.st_mode)) {
	    printf("fail: incorrect mode: %d\n", (S_IAMB & st.st_mode));
	} else {
	    printf("succeed\n");
	}
    }

    nsfio_close(nsc, fd);
    nsfio_unlink(nsc, TEST_FILE1);
}


void
test_chown(nsfio_t * nsc)
{
    int		rv;
    int		fd;
    int		errno_save;

    printf("chown: ");

    rv = nsfio_chown(nsc, TEST_FILE1, 99, 99);
    if (0 == rv) {
	printf("fail: should fail on non-existent file\n");
	return;
    } else if (ENOENT != errno) {
	printf("fail: invalid errno: %d should be ENOENT (%d)\n",
	       errno, ENOENT);
	return;
    }

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    nsfio_close(nsc, fd);

    rv = nsfio_chown(nsc, TEST_FILE1, 99, 99);
    errno_save = errno;

    switch (geteuid()) {
    case 0:
	if (0 != rv) {
	    printf("fail: uid = %d: should succeed\n", geteuid());
	} else {
	    printf("succeed\n");
	}
	break;
    default:
	if (0 == rv) {
	    printf("fail: uid = %d: should fail\n", geteuid());
	} else if (EPERM != errno_save) {
	    printf("invalid errno: %d should be EPERM (%d)\n", 
		   errno_save, EPERM);
	} else {
	    printf("succeed\n");
	}
	break;
    }

    nsfio_unlink(nsc, TEST_FILE1);
}


#if 0
void
test_lchown(nsfio_t * nsc)
{
    int		rv;
    int		fd;
    int		errno_save;
    uid_t	uid;

    printf("lchown: ");

    uid = geteuid();

    rv = nsfio_lchown(nsc, TEST_FILE1, 99, 99);
    if (0 == rv) {
	printf("fail: should fail on non-existent file\n");
	return;
    } else if ((0 == uid) && (ENOENT != errno)) {
	printf("fail: invalid errno: %d should be ENOENT (%d)\n",
	       errno, ENOENT);
	return;
    } else if ((0 != uid) && (EPERM != errno)) {
	printf("fail: invalid errno: %d should be EPERM (%d)\n",
	       errno, EPERM);
	return;
    }

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    nsfio_close(nsc, fd);

    rv = nsfio_lchown(nsc, TEST_FILE1, 99, 99);
    errno_save = errno;

    switch (geteuid()) {
    case 0:
	if (0 != rv) {
	    printf("fail: uid = %d: should succeed\n", geteuid());
	} else {
	    printf("succeed\n");
	}
	break;
    default:
	if (0 == rv) {
	    printf("fail: uid = %d: should fail\n", geteuid());
	} else if (EPERM != errno_save) {
	    printf("invalid errno: %d should be EPERM (%d)\n", 
		   errno_save, EPERM);
	} else {
	    printf("succeed\n");
	}
	break;
    }

    nsfio_unlink(nsc, TEST_FILE1);
}
#endif /* 0 */


void
test_fchown(nsfio_t * nsc)
{
    int		rv;
    int		fd;
    int		errno_save;
    uid_t	uid;

    printf("fchown: ");

    uid = geteuid();

    rv = nsfio_fchown(nsc, 99, 99, 99);
    if (0 == rv) {
	printf("fail: should fail on non-existent file\n");
	return;
    } else if (EBADF != errno) {
	printf("fail: invalid errno: %d should be EBADF (%d)\n", errno, EBADF);
	return;
    }

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);

    rv = nsfio_fchown(nsc, fd, 99, 99);
    errno_save = errno;

    switch (geteuid()) {
    case 0:
	if (0 != rv) {
	    printf("fail: uid = %d: should succeed\n", geteuid());
	} else {
	    printf("succeed\n");
	}
	break;
    default:
	if (0 == rv) {
	    printf("fail: uid = %d: should fail\n", geteuid());
	} else if (EPERM != errno_save) {
	    printf("invalid errno: %d should be EPERM (%d)\n", 
		   errno_save, EPERM);
	} else {
	    printf("succeed\n");
	}
	break;
    }

    nsfio_close(nsc, fd);
    nsfio_unlink(nsc, TEST_FILE1);
}


void
test_fpathconf(nsfio_t * nsc)
{
    long	rv;
    int		fd;

    printf("fpathconf: ");

    rv = nsfio_fpathconf(nsc, 99, _PC_PATH_MAX);
    if (-1 != rv) {
	printf("fail: should fail\n");
	return;
    } else if (EBADF != errno) {
	printf("fail: invalid errno: %d should be EBADF (%d)\n",
	       errno, EBADF);
	return;
    }

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);

    rv = nsfio_fpathconf(nsc, fd, _PC_PATH_MAX);
    if (-1 != rv) {
	printf("succeed\n");
    } else {
	printf("fail: %ld\n", rv);
    }

    nsfio_close(nsc, fd);
    nsfio_unlink(nsc, TEST_FILE1);
}


void
test_pathconf(nsfio_t * nsc)
{
    long	rv;
    int		fd;

    printf("pathconf: ");

    rv = nsfio_pathconf(nsc, TEST_FILE1, _PC_PATH_MAX);
    if (-1 != rv) {
	printf("fail: should fail\n");
	return;
    } else if (ENOENT != errno) {
	printf("fail: invalid errno: %d should be ENOENT (%d)\n",
	       errno, ENOENT);
	return;
    }

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    nsfio_close(nsc, fd);

    rv = nsfio_pathconf(nsc, TEST_FILE1, _PC_PATH_MAX);
    if (-1 != rv) {
	printf("succeed\n");
    } else {
	printf("fail: %lu\n", rv);
    }

    nsfio_unlink(nsc, TEST_FILE1);
}


void
test_utime(nsfio_t * nsc)
{
    int	rv;
    int	fd;

    printf("utime: ");

    rv = nsfio_utime(nsc, TEST_FILE1, NULL);
    if (-1 != rv) {
	printf("fail: should fail");
	return;
    } else if (ENOENT != errno) {
	printf("fail: invalid errno: %d should be ENOENT (%d)\n",
	       errno, ENOENT);
	return;
    }

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    nsfio_close(nsc, fd);

    rv = nsfio_utime(nsc, TEST_FILE1, NULL);
    if (-1 != rv) {
	printf("succeed\n");
    } else {
	printf("fail: %d\n", rv);
    }

    nsfio_unlink(nsc, TEST_FILE1);
}


void
test_utimes(nsfio_t * nsc)
{
    int	rv;
    int	fd;

    printf("utimes: ");

    rv = nsfio_utimes(nsc, TEST_FILE1, NULL);
    if (-1 != rv) {
	printf("fail: should fail");
	return;
    } else if (ENOENT != errno) {
	printf("fail: invalid errno: %d should be ENOENT (%d)\n",
	       errno, ENOENT);
	return;
    }

    fd = nsfio_open(nsc, TEST_FILE1, O_WRONLY | O_CREAT | O_TRUNC, 0600);
    nsfio_close(nsc, fd);

    rv = nsfio_utimes(nsc, TEST_FILE1, NULL);
    if (-1 != rv) {
	printf("succeed\n");
    } else {
	printf("fail: %d\n", rv);
    }

    nsfio_unlink(nsc, TEST_FILE1);
}


int
main()
{
    nsfio_t *		nsc;

    nsfio__nsc_create =
	(iml__nsc_create_t)(nsfio_get_function("_nsc_create"));
    if (NULL == nsfio__nsc_create) fprintf(stderr, "_nsc_create: fail\n");
    nsfio__nsc_free = (iml__nsc_free_t)(nsfio_get_function("_nsc_free"));
    if (NULL == nsfio__nsc_free) fprintf(stderr, "_nsc_free: fail\n");
    nsfio_access = (iml_nsc_access_t)(nsfio_get_function("access"));
    if (NULL == nsfio_access) fprintf(stderr, "access: fail\n");
    nsfio_chmod = (iml_nsc_chmod_t)(nsfio_get_function("chmod"));
    if (NULL == nsfio_chmod) fprintf(stderr, "chmod: fail\n");
    nsfio_fchmod = (iml_nsc_fchmod_t)(nsfio_get_function("fchmod"));
    if (NULL == nsfio_fchmod) fprintf(stderr, "fchmod: fail\n");
    nsfio_chown = (iml_nsc_chown_t)(nsfio_get_function("chown"));
    if (NULL == nsfio_chown) fprintf(stderr, "chown: fail\n");
#if 0
    nsfio_lchown = (iml_nsc_lchown_t)(nsfio_get_function("lchown"));
    if (NULL == nsfio_lchown) fprintf(stderr, "chown: lfail\n");
#endif /* 0 */
    nsfio_fchown = (iml_nsc_fchown_t)(nsfio_get_function("fchown"));
    if (NULL == nsfio_fchown) fprintf(stderr, "fchown: fail\n");
    nsfio_close = (iml_nsc_close_t)(nsfio_get_function("close"));
    if (NULL == nsfio_close) fprintf(stderr, "close: fail\n");
    nsfio_closedir = (iml_nsc_closedir_t)(nsfio_get_function("closedir"));
    if (NULL == nsfio_closedir) fprintf(stderr, "closedir: fail\n");
    nsfio_creat = (iml_nsc_creat_t)(nsfio_get_function("creat"));
    if (NULL == nsfio_creat) fprintf(stderr, "creat: fail\n");
    nsfio_fcntl = (iml_nsc_fcntl_t)(nsfio_get_function("fcntl"));
    if (NULL == nsfio_fcntl) fprintf(stderr, "fcntl: fail\n");
    nsfio_fpathconf = (iml_nsc_fpathconf_t)(nsfio_get_function("fpathconf"));
    if (NULL == nsfio_fpathconf) fprintf(stderr, "fpathconf: fail\n");
    nsfio_fstat = (iml_nsc_fstat_t)(nsfio_get_function("fstat"));
    if (NULL == nsfio_fstat) fprintf(stderr, "fstat: fail\n");
    nsfio_ftruncate = (iml_nsc_ftruncate_t)(nsfio_get_function("ftruncate"));
    if (NULL == nsfio_ftruncate) fprintf(stderr, "ftruncate: fail\n");
    nsfio_link = (iml_nsc_link_t)(nsfio_get_function("link"));
    if (NULL == nsfio_link) fprintf(stderr, "link: fail\n");
    nsfio_lseek = (iml_nsc_lseek_t)(nsfio_get_function("lseek"));
    if (NULL == nsfio_lseek) fprintf(stderr, "lseek: fail\n");
    nsfio_lstat = (iml_nsc_lstat_t)(nsfio_get_function("lstat"));
    if (NULL == nsfio_lstat) fprintf(stderr, "lstat: fail\n");
    nsfio_mkdir = (iml_nsc_mkdir_t)(nsfio_get_function("mkdir"));
    if (NULL == nsfio_mkdir) fprintf(stderr, "mkdir: fail\n");
    nsfio_open = (iml_nsc_open_t)(nsfio_get_function("open"));
    if (NULL == nsfio_open) fprintf(stderr, "open: fail\n");
    nsfio_opendir = (iml_nsc_opendir_t)(nsfio_get_function("opendir"));
    if (NULL == nsfio_opendir) fprintf(stderr, "opendir: fail\n");
    nsfio_pathconf = (iml_nsc_pathconf_t)(nsfio_get_function("pathconf"));
    if (NULL == nsfio_pathconf) fprintf(stderr, "pathconf: fail\n");
    nsfio_read = (iml_nsc_read_t)(nsfio_get_function("read"));
    if (NULL == nsfio_read) fprintf(stderr, "read: fail\n");
    nsfio_readdir = (iml_nsc_readdir_t)(nsfio_get_function("readdir"));
    if (NULL == nsfio_readdir) fprintf(stderr, "readdir: fail\n");
    nsfio_readv = (iml_nsc_readv_t)(nsfio_get_function("readv"));
    if (NULL == nsfio_readv) fprintf(stderr, "readv: fail\n");
    nsfio_rename = (iml_nsc_rename_t)(nsfio_get_function("rename"));
    if (NULL == nsfio_rename) fprintf(stderr, "rename: fail\n");
    nsfio_rmdir = (iml_nsc_rmdir_t)(nsfio_get_function("rmdir"));
    if (NULL == nsfio_rmdir) fprintf(stderr, "rmdir: fail\n");
    nsfio_stat = (iml_nsc_stat_t)(nsfio_get_function("stat"));
    if (NULL == nsfio_stat) fprintf(stderr, "stat: fail\n");
    nsfio_symlink = (iml_nsc_symlink_t)(nsfio_get_function("symlink"));
    if (NULL == nsfio_symlink) fprintf(stderr, "symlink: fail\n");
    nsfio_truncate = (iml_nsc_truncate_t)(nsfio_get_function("truncate"));
    if (NULL == nsfio_truncate) fprintf(stderr, "truncate: fail\n");
    nsfio_unlink = (iml_nsc_unlink_t)(nsfio_get_function("unlink"));
    if (NULL == nsfio_unlink) fprintf(stderr, "unlink: fail\n");
    nsfio_utime = (iml_nsc_utime_t)(nsfio_get_function("utime"));
    if (NULL == nsfio_utime) fprintf(stderr, "utime: fail\n");
    nsfio_utimes = (iml_nsc_utimes_t)(nsfio_get_function("utimes"));
    if (NULL == nsfio_utimes) fprintf(stderr, "utimes: fail\n");
    nsfio_write = (iml_nsc_write_t)(nsfio_get_function("write"));
    if (NULL == nsfio_write) fprintf(stderr, "write: fail\n");
    nsfio_writev = (iml_nsc_writev_t)(nsfio_get_function("writev"));
    if (NULL == nsfio_writev) fprintf(stderr, "writev: fail\n");

    nsc = nsfio__nsc_create("test", IML_NSC_TYPE_DESKTOP, NULL);

    test_prep(nsc);
    test_open(nsc);
    test_read(nsc);
    test_readv(nsc);
    test_write(nsc);
    test_writev(nsc);
    test_close(nsc);
    test_creat(nsc);
    test_lseek(nsc);
    test_stat(nsc);
    test_lstat(nsc);
    test_fstat(nsc);
    test_mkkdir(nsc);
    test_rmdir(nsc);
    test_symlink(nsc);
    test_link(nsc);
    test_unlink(nsc);
    test_rename(nsc);
    test_fcntl(nsc);
    test_truncate(nsc);
    test_ftruncate(nsc);
    test_opendir(nsc);
    test_readdir(nsc);
    test_closedir(nsc);
    test_access(nsc);
    test_chmod(nsc);
    test_fchmod(nsc);
    test_chown(nsc);
#if 0
    test_lchown(nsc);
#endif /* 0 */
    test_fchown(nsc);
    test_fpathconf(nsc);
    test_pathconf(nsc);
    test_utime(nsc);
    test_utimes(nsc);

    nsfio__nsc_free(nsc);

    return 0;
}


/* Local Variables: */
/* c-file-style: "iiim-project" */
/* End: */
