/* ----------------------------------------------
*/
#include "afpcmd.h"
#include "afphelper.h"
#include "testhelper.h"

/* ------------------------- */
STATIC void test6()
{
    int  dir;
    char *name = "test6 dir";
    uint16_t vol = VolID;
    ENTER_TEST

    if (!(dir = FPCreateDir(Conn, vol, DIRDID_ROOT, name))) {
        test_failed();
        goto test_exit;
    }

    FAIL(FPDelete(Conn, vol, DIRDID_ROOT, name))

    if (!(dir = FPCreateDir(Conn, vol, DIRDID_ROOT, name))) {
        test_failed();
        goto test_exit;
    }

    FAIL(FPDelete(Conn, vol, dir, ""))
test_exit:
    exit_test("FPCreateDir:test6: create dir");
}

/* ------------------------- */
STATIC void test26()
{
    char *name = "test26 dir";
    int pdir;
    uint16_t vol = VolID;
    ENTER_TEST

    if (!Conn2) {
        test_skipped(T_CONN2);
        goto test_exit;
    }

    if (!(pdir = no_access_folder(vol, DIRDID_ROOT, name))) {
        goto test_exit;
    }

    if (FPGetFileDirParams(Conn, vol, DIRDID_ROOT, name, 0,
                           (1 <<  DIRPBIT_LNAME) | (1 << DIRPBIT_PDID) | (1 << DIRPBIT_DID) |
                           (1 << DIRPBIT_ACCESS))) {
        test_failed();
        goto fin;
    }

    /* FIXME: FPEnumerate* uses my_dsi_data_receive. See afphelper.c:delete_directory_tree() */
    FPEnumerate(Conn, vol, DIRDID_ROOT, "",
                (1 << FILPBIT_LNAME) | (1 << FILPBIT_FNUM),
                (1 << DIRPBIT_LNAME) | (1 << DIRPBIT_PDID) | (1 << DIRPBIT_DID) |
                (1 << DIRPBIT_ACCESS)
               );

    if (FPGetFileDirParams(Conn, vol, pdir, "", 0,
                           (1 <<  DIRPBIT_LNAME) | (1 << DIRPBIT_PDID) | (1 << DIRPBIT_DID) |
                           (1 << DIRPBIT_ACCESS))
       ) {
        test_failed();
    }

fin:
    delete_folder(vol, DIRDID_ROOT, name);
test_exit:
    exit_test("FPCreateDir:test26: folder without right access");
}

/* ------------------------- */
STATIC void test45()

{
    int  dir = 0;
    char *ndir = "t45 no access";
    char *rodir = "t45 read only access";
    int pdir = 0;
    int rdir = 0;
    uint16_t vol = VolID;
    DSI *dsi;
    dsi = &Conn->dsi;
    ENTER_TEST

    if (!Conn2) {
        test_skipped(T_CONN2);
        goto test_exit;
    }

    if (!(pdir = no_access_folder(vol, DIRDID_ROOT, ndir))) {
        goto test_exit;
    }

    if (!(rdir = read_only_folder(vol, DIRDID_ROOT, rodir))) {
        goto fin;
    }

    dir  = FPCreateDir(Conn, vol, DIRDID_ROOT, "t45 no access/file");

    if (dir || dsi->header.dsi_code != ntohl(AFPERR_ACCESS)) {
        test_failed();
        goto fin;
    }

    if (dir) {
        FAIL(FPDelete(Conn, vol, dir, ""))
        goto fin;
    }

    dir  = FPCreateDir(Conn, vol, pdir, "t45 file");

    if (dir || dsi->header.dsi_code != ntohl(AFPERR_ACCESS)) {
        test_failed();
        goto fin;
    }

    if (dir) {
        FAIL(FPDelete(Conn, vol, dir, ""))
        goto fin;
    }

    dir  = FPCreateDir(Conn, vol, DIRDID_ROOT, rodir);

    if (dir || dsi->header.dsi_code != htonl(AFPERR_EXIST)) {
        test_failed();
        goto fin;
    }

fin:
    delete_folder(vol, DIRDID_ROOT, ndir);

    if (rdir) {
        delete_folder(vol, DIRDID_ROOT, rodir);
    }

test_exit:
    exit_test("FPCreateDir:test45: Folder Creation");
}

/* -------------------------- */
static int create_deleted_folder(uint16_t vol, char *name)
{
    uint16_t vol2;
    int tdir;
    DSI *dsi2;
    tdir  = FPCreateDir(Conn, vol, DIRDID_ROOT, name);

    if (!tdir) {
        test_nottested();
        return 0;
    }

    if (FPGetFileDirParams(Conn, vol, tdir, "", 0,
                           (1 << DIRPBIT_PDINFO) | (1 << DIRPBIT_OFFCNT))) {
        test_nottested();
        return 0;
    }

    dsi2 = &Conn2->dsi;
    vol2  = FPOpenVol(Conn2, Vol);

    if (FPDelete(Conn2, vol2, DIRDID_ROOT, name)) {
        test_nottested();
        FAIL(FPDelete(Conn, vol, tdir, ""))
        FAIL(FPCloseVol(Conn2, vol2))
        return 0;
    }

    FAIL(FPCloseVol(Conn2, vol2))
    return tdir;
}

/* ----------- */
STATIC void test175()
{
    char *tname = "test175";
    int tdir, dir;
    uint16_t vol = VolID;
    DSI *dsi;
    unsigned int ret;
    ENTER_TEST

    if (!Conn2) {
        test_skipped(T_CONN2);
        goto test_exit;
    }

    dsi = &Conn->dsi;

    /* ---- file.c ---- */
    if (!(tdir = create_deleted_folder(vol, tname))) {
        goto test_exit;
    }

    ret = FPCreateFile(Conn, vol, 0, tdir, tname);

    /* FIXME ? */
    if (not_valid(ret, /* MAC */AFPERR_NOOBJ, AFPERR_PARAM)) {
        test_failed();
    }

    /* ---- directory.c ---- */
    if (!(tdir = create_deleted_folder(vol, tname))) {
        goto test_exit;
    }

    dir  = FPCreateDir(Conn, vol, tdir, tname);
    ret = dsi->header.dsi_code;

    if (dir || not_valid(ret, AFPERR_NOOBJ, AFPERR_PARAM)) {
        test_failed();

        if (dir) {
            FPDelete(Conn, vol, dir, "");
        }
    }

    /* ----------- */
    tname = ".test175";

    if (!(tdir = create_deleted_folder(vol, tname))) {
        goto test_exit;
    }

    dir  = FPCreateDir(Conn, vol, tdir, tname);
    ret = dsi->header.dsi_code;

    if (dir || not_valid(ret, AFPERR_NOOBJ, AFPERR_PARAM)) {
        test_failed();

        if (dir) {
            FPDelete(Conn, vol, dir, "");
        }
    }

    /* ----------- */
    tname = ".test175b";

    if (!(tdir = create_deleted_folder(vol, tname))) {
        goto test_exit;
    }

    dir  = FPCreateDir(Conn, vol, DIRDID_ROOT, tname);

    if (!dir) {
        test_failed();
    } else {
        FPDelete(Conn, vol, dir, "");
    }

test_exit:
    exit_test("FPCreateDir:test175: did error two users in  folder did=<deleted> name=test175");
}

/* ----------- */
STATIC void test198()
{
    char *name = "test198 dir";
    char *name1 = "test198 subdir";
    char *name2 = "test198 dir/test198 subdir";
    int tdir, tdir1 = 0;
    uint16_t vol = VolID;
    uint16_t bitmap = (1 <<  DIRPBIT_LNAME) | (1 << DIRPBIT_PDID) |
                      (1 << DIRPBIT_DID) | (1 << DIRPBIT_UID) |
                      (1 << DIRPBIT_GID) | (1 << DIRPBIT_ACCESS);
    uint16_t vol2;
    DSI *dsi2;
    unsigned int ret;
    ENTER_TEST

    if (!Conn2) {
        test_skipped(T_CONN2);
        goto test_exit;
    }

    tdir  = FPCreateDir(Conn, vol, DIRDID_ROOT, name);

    if (!tdir) {
        test_nottested();
        goto test_exit;
    }

    tdir1  = FPCreateDir(Conn, vol, tdir, name1);

    if (!tdir1) {
        test_nottested();
        goto fin;
    }

    FAIL(FPGetFileDirParams(Conn, vol, tdir, "", 0, bitmap))
    FAIL(FPGetFileDirParams(Conn, vol, tdir1, "", 0, bitmap))
    dsi2 = &Conn2->dsi;
    vol2  = FPOpenVol(Conn2, Vol);

    if (vol2 == 0xffff) {
        test_nottested();
        goto fin;
    }

    ret = FPDelete(Conn2, vol2,  DIRDID_ROOT, name2);

    if (not_valid(ret, AFPERR_ACCESS, 0)) {
        test_failed();
    }

    if (ret) {
        FAIL(FPDelete(Conn, vol, tdir1, ""))
    }

    tdir1 = 0;

    if (FPDelete(Conn2, vol2,  DIRDID_ROOT, name)) {
        test_failed();
        FAIL(FPDelete(Conn, vol, tdir, ""))
    }

    tdir = 0;
fin:
    FAIL(tdir && FPDelete(Conn, vol, tdir, ""))
    FAIL(tdir1 && FPDelete(Conn, vol, tdir1, ""))
test_exit:
    exit_test("FPCreateDir:test198: second user delete folder");
}

/* ----------- */
STATIC void test357()
{
    char *name = "test357 dir";
    int tdir;
    uint16_t vol = VolID;
    int  ofs =  3 * sizeof(uint16_t);
    struct afp_filedir_parms filedir;
    uint16_t bitmap = (1 << DIRPBIT_ATTR) | (1 << DIRPBIT_FINFO) |
                      (1 << DIRPBIT_CDATE) |
                      (1 << DIRPBIT_BDATE) | (1 << DIRPBIT_MDATE) | (1 << DIRPBIT_UID) |
                      (1 << DIRPBIT_GID);
    uint16_t vol2;
    const DSI *dsi;
    const DSI *dsi2;
    unsigned int ret;
    ENTER_TEST

    if (!Conn2) {
        test_skipped(T_CONN2);
        goto test_exit;
    }

    dsi = &Conn->dsi;
    tdir  = FPCreateDir(Conn, vol, DIRDID_ROOT, name);

    if (!tdir) {
        test_nottested();
        goto test_exit;
    }

    FAIL(FPGetFileDirParams(Conn, vol, tdir, "", 0, bitmap))
    filedir.isdir = 1;
    afp_filedir_unpack(&filedir, dsi->data + ofs, 0, bitmap);
    filedir.access[0] = 0;
    filedir.access[1] = 0;
    filedir.access[2] = 0;
    filedir.access[3] = 7; /* only owner */
    FAIL(FPSetDirParms(Conn, vol, tdir, "", (1 << DIRPBIT_ACCESS), &filedir))
    FAIL(FPGetFileDirParams(Conn, vol, tdir, "", 0, bitmap))
    dsi2 = &Conn2->dsi;
    vol2  = FPOpenVol(Conn2, Vol);

    if (vol2 == 0xffff) {
        test_nottested();
        FAIL(FPDelete(Conn, vol, tdir, ""))
        goto test_exit;
    }

    filedir.isdir = 1;
    afp_filedir_unpack(&filedir, dsi->data + ofs, 0, bitmap);
    filedir.attr = ATTRBIT_NODELETE | ATTRBIT_SETCLR ;
    FAIL(FPSetDirParms(Conn2, vol2, DIRDID_ROOT, name, bitmap, &filedir))

    if (ntohl(AFPERR_OLOCK) != FPDelete(Conn, vol, DIRDID_ROOT, name)) {
        test_failed();
        goto test_exit;
    }

    filedir.attr = ATTRBIT_NODELETE;
    FAIL(FPSetDirParms(Conn2, vol2, DIRDID_ROOT, name, bitmap, &filedir))
    ret = FPDelete(Conn2, vol2,  DIRDID_ROOT, name);

    if (ret) {
        test_failed();
        FAIL(FPDelete(Conn, vol, tdir, ""))
    }

test_exit:
    exit_test("FPCreateDir:test357: admin user");
}

/* ----------- */
void FPCreateDir_test()
{
    ENTER_TESTSET
    test6();
    test26();
    test45();
    test175();
    test198();
}
