adtools/clib2

View on GitHub
library/unistd_common_pathconf.c

Summary

Maintainability
Test Coverage
/*
 * $Id: unistd_common_pathconf.c,v 1.4 2008-04-16 07:38:10 obarthel Exp $
 *
 * :ts=4
 *
 * Portable ISO 'C' (1994) runtime library for the Amiga computer
 * Copyright (c) 2002-2015 by Olaf Barthel <obarthel (at) gmx.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:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Neither the name of Olaf Barthel nor the names of contributors
 *     may be used to endorse or promote products derived from this
 *     software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
 */

#ifndef _STDLIB_NULL_POINTER_CHECK_H
#include "stdlib_null_pointer_check.h"
#endif /* _STDLIB_NULL_POINTER_CHECK_H */

/****************************************************************************/

#ifndef _UNISTD_HEADERS_H
#include "unistd_headers.h"
#endif /* _UNISTD_HEADERS_H */

/****************************************************************************/

/* The following is not part of the ISO 'C' (1994) standard. */

/****************************************************************************/

#ifndef ID_CON
#define ID_CON (0x434F4E00L) /* 'CON\0' */
#endif /* ID_CON */

#ifndef ID_RAWCON
#define ID_RAWCON (0x52415700L) /* 'RAW\0' */
#endif /* ID_RAWCON */

#ifndef ID_BUSY_DISK
#define ID_BUSY_DISK (0x42555359L) /* 'BUSY' */
#endif /* ID_LONGNAME_DOS_DISK */

#ifndef ID_LONGNAME_DOS_DISK
#define ID_LONGNAME_DOS_DISK (0x444F5306L) /* 'DOS\6' */
#endif /* ID_LONGNAME_DOS_DISK */

#ifndef ID_LONGNAME_FFS_DISK
#define ID_LONGNAME_FFS_DISK (0x444F5307L) /* 'DOS\7' */
#endif /* ID_LONGNAME_FFS_DISK */

/****************************************************************************/

struct fs_info
{
    ULONG    dos_type;
    int        name_max,path_max;
    int        link_max,symlink_max;
    int        file_size_bits;
};

/****************************************************************************/

static const struct fs_info fs_info[] =
{
    {ID_NO_DISK_PRESENT,    0,        0,        0,    0,    0},        /* No disk */
    {ID_UNREADABLE_DISK,    0,        0,        0,    0,    0},        /* BAD\0 */
    {ID_BUSY_DISK,            0,        0,        0,    0,    0},        /* BUSY - Diskchange in progress? */
    {ID_CON,                0,        0,        0,    0,    0},        /* CON\0 - Not really a disk. */
    {ID_RAWCON,                0,        0,        0,    0,    0},        /* RAW\0 - Not really a disk. */
    {ID_NOT_REALLY_DOS,        0,        0,        0,    0,    0},        /* Unreadable disk. */
    {ID_KICKSTART_DISK,        0,        0,        0,    0,    0},        /* Kickstart disk. */
    {ID_MSDOS_DISK,            8,        31,        0,    0,    30},    /* MSDOS - TODO: Check what the limits really are. */
    {ID_DOS_DISK,            30,        254,    -1,    -1,    31},    /* DOS\0 = OFS */
    {ID_FFS_DISK,            30,        254,    -1,    -1,    31},    /* DOS\1 = FFS */
    {ID_INTER_DOS_DISK,        30,        254,    -1,    -1,    31},    /* DOS\2 = OFS INTL */
    {ID_INTER_FFS_DISK,        30,        254,    -1,    -1,    31},    /* DOS\3 = FFS INTL */
    {ID_FASTDIR_DOS_DISK,    30,        254,    -1,    -1,    31},    /* DOS\4 = OFS DC */
    {ID_FASTDIR_FFS_DISK,    30,        254,    -1,    -1,    31},    /* DOS\5 = FFS DC */
    {ID_LONGNAME_DOS_DISK,    107,    8192,    -1,    -1,    31},    /* DOS\6 = OFS LONGNAMES */
    {ID_LONGNAME_FFS_DISK,    107,    8192,    -1,    -1,    63},    /* DOS\7 = FFS LONGNAMES */
    {0x53465300,            107,    8192,    0,    -1,    31},    /* SFS\0 = Smartfilesystem */
    {0x53465302,            107,    8192,    0,    -1,    63},    /* SFS\2 = Smartfilesystem2 */
    {0x50465300,            30,        254,    0,    0,    31},    /* PFS\0 = Professional File System */
    {0x46545854,            0,        0,        0,    0,    0},        /* FTXT - Textclip device */
};

/****************************************************************************/

long
__pathconf(struct MsgPort *port,int name)
{
    ULONG dos_type = 0;
    size_t fs_index = 0;
    long ret = -1;

    if(port != NULL)
    {
        D_S(struct InfoData,id);

        if(DoPkt(port,ACTION_IS_FILESYSTEM,0,0,0,0,0) == DOSFALSE) /* Not a filesystem. */
        {
            SHOWMSG("Not a filesystem.");

            __set_errno(ENODEV);
            goto out;
        }

        if(DoPkt(port,ACTION_DISK_INFO,MKBADDR(id),0,0,0,0))    /* Managed to obtain disk info. */
        {
            size_t i;

            switch(id->id_DiskState)
            {
                case ID_VALIDATING:    /* Consider this an error condition? */
                case ID_WRITE_PROTECTED:
                case ID_VALIDATED:

                    dos_type = id->id_DiskType;

                    /* See if we know anything about this file-system */
                    for(i = 0 ; i < NUM_ENTRIES(fs_info) ; i++)
                    {
                        if(dos_type == fs_info[i].dos_type)
                        {
                            fs_index = i;
                            break;
                        }
                    }

                    break;

                default:

                    SHOWMSG("Invalid disk state.");
                    break;
            }
        }
        else
        {
            /* Treat error as no disk present by having default fs_index=0 */
            SHOWMSG("Unable to query DISK_INFO");
        }
    }

    switch(name)
    {
        case _PC_FILESIZEBITS:

            ret = fs_info[fs_index].file_size_bits;
            break;

        case _PC_LINK_MAX:

            ret = fs_info[fs_index].link_max;
            break;

        case _PC_MAX_CANON:

            ret = 510;    /* I could not find any documentation regarding this. */
            break;

        case _PC_MAX_INPUT:

            #if defined(__amigaos4__)
            {
                uint32 Bufsize;
                struct TagItem TagList[2]=
                {
                    {DC_FHBufferR,    (ULONG)&Bufsize},
                    {TAG_DONE,        0}
                };

                DosControl(TagList);
                ret = Bufsize;    /* Default is 2048 bytes. */
            }
            #else
            {
                ret = 204;
            }
            #endif    /* __amigaos4__ */

            break;

        case _PC_NAME_MAX:

            ret = fs_info[fs_index].name_max;
            break;

        case _PC_PATH_MAX:

            ret = fs_info[fs_index].path_max;
            break;

        case _PC_PIPE_BUF:

            ret = 512;    /* One buffer. The PIPE: device usually has 8 of these. */
            break;

        case _PC_XATTR_ENABLED:

            ret = 0;
            break;

        case _PC_XATTR_EXISTS:

            ret = 0;
            break;

        case _PC_CHOWN_RESTRICTED:

            ret = 0;
            break;

        case _PC_NO_TRUNC:

            ret = 0;
            break;

        case _PC_VDISABLE:

            ret = 0;    /* TODO: Implement this in the termios emulation. */
            break;

        case _PC_ASYNC_IO:

            ret = 0;
            break;

        case _PC_PRIO_IO:

            ret = 0;
            break;

        case _PC_SYNC_IO:

            ret = 0;
            break;

        case _PC_SYMLINK_MAX:

            ret = fs_info[fs_index].symlink_max;
            break;

        case _PC_DOSTYPE:    /* Amiga-specific extension. */

            ret = dos_type;
            break;

        default:

            SHOWMSG("Invalid option name");
            __set_errno(EINVAL);
            goto out;
    }

 out:

    return(ret);
}