/* Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 *
 * @author Mladen Turk
 * @version $Id: dir.c 1442587 2013-02-05 13:49:48Z rjung $
 */
 
#include "tcn.h"
#include "apr_file_io.h"

TCN_IMPLEMENT_CALL(jint, Directory, make)(TCN_STDARGS, jstring path,
                                          jint perm, jlong pool)
{
    apr_pool_t *p = J2P(pool, apr_pool_t *);
    TCN_ALLOC_CSTRING(path);
    apr_status_t rv;

    UNREFERENCED(o);
    rv = apr_dir_make(J2S(path), (apr_fileperms_t)perm, p);
    TCN_FREE_CSTRING(path);
    return (jint)rv;
}

TCN_IMPLEMENT_CALL(jint, Directory, makeRecursive)(TCN_STDARGS, jstring path,
                                                    jint perm, jlong pool)
{
    apr_pool_t *p = J2P(pool, apr_pool_t *);
    TCN_ALLOC_CSTRING(path);
    apr_status_t rv;

    UNREFERENCED(o);
    rv = apr_dir_make_recursive(J2S(path), (apr_fileperms_t)perm, p);
    TCN_FREE_CSTRING(path);
    return (jint)rv;
}

TCN_IMPLEMENT_CALL(jint, Directory, remove)(TCN_STDARGS, jstring path,
                                            jlong pool)
{
    apr_pool_t *p = J2P(pool, apr_pool_t *);
    TCN_ALLOC_CSTRING(path);
    apr_status_t rv;

    UNREFERENCED(o);
    rv = apr_dir_remove(J2S(path), p);
    TCN_FREE_CSTRING(path);
    return (jint)rv;
}

TCN_IMPLEMENT_CALL(jstring, Directory, tempGet)(TCN_STDARGS, jlong pool)
{
    apr_pool_t *p = J2P(pool, apr_pool_t *);
    jstring name = NULL;
    const char *tname;

    UNREFERENCED(o);
    if (apr_temp_dir_get(&tname, p) == APR_SUCCESS)
        name = AJP_TO_JSTRING(tname);

    return name;
}

TCN_IMPLEMENT_CALL(jlong, Directory, open)(TCN_STDARGS, jstring path,
                                      jlong pool)
{
    apr_pool_t *p = J2P(pool, apr_pool_t *);
    apr_dir_t *d = NULL;
    TCN_ALLOC_CSTRING(path);

    UNREFERENCED(o);
    TCN_THROW_IF_ERR(apr_dir_open(&d, J2S(path), p), d);

cleanup:
    TCN_FREE_CSTRING(path);
    return P2J(d);
}

TCN_IMPLEMENT_CALL(jint, Directory, close)(TCN_STDARGS, jlong dir)
{
    apr_dir_t *d = J2P(dir, apr_dir_t *);
    UNREFERENCED_STDARGS;
    return (jint)apr_dir_close(d);
}

TCN_IMPLEMENT_CALL(jint, Directory, rewind)(TCN_STDARGS, jlong dir)
{
    apr_dir_t *d = J2P(dir, apr_dir_t *);
    UNREFERENCED_STDARGS;
    return (jint)apr_dir_rewind(d);
}
