jens-maus/amissl

View on GitHub
libcmt/file.c

Summary

Maintainability
Test Coverage
#include <dos/dos.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <errno.h>
#include <internal/amissl.h>
#include "libcmt.h"

extern struct MinList __filelist; /* list of open files (fflush() needs also access) */

extern LOCK_DECLARE(__filelist_cs);

FILE *freopen(const char *filename,const char *mode,FILE *stream)
{
    int error;
    error=fflush(stream);
#if 0
    if(stream->file>2)
    {
        Close(stream->_file);
        if(stream->name!=NULL) /* file is temporary */
        {
            BPTR cd;
            cd=CurrentDir(stream->tmpdir); /* cd t: */
            if(!DeleteFile(stream->name))    /* delete file */
            {
                SetAmiSSLerrno(__io2errno(IoErr()));
                error=1;
            }
            free(stream->name); /* free filename */
            stream->name=NULL;
            UnLock(CurrentDir(cd)); /* cd back, unlock t: */
        }
        stream->file=0l;
    }
    if(error)
        return NULL;
#endif

    if(filename!=NULL)
    {
        long file;
        long flags=MODE_OLDFILE;
        int append=0,plus=1;
        if(mode!=NULL)
        {
            switch(mode[0])
            {
                case 'r':
                    TOFILE(stream)->_flag |= _IOREAD;
                    break;
                case 'w':
                    flags=MODE_NEWFILE;
                    TOFILE(stream)->_flag |= _IOWRT;
                    break;
                case 'a':
                    flags=MODE_READWRITE;
                    TOFILE(stream)->_flag |= _IOWRT;
                    append=1;
                    break;
                default:
                    return NULL;
            }
            if(mode[1]=='b')
                plus=2;
            switch(mode[plus])
            {
                case '+':
                    if(mode[plus+1])
                        return NULL; // TOFILE(stream)->_flag |= _IORW;
                    break;
                case '\0':
                    break;
                default:
                    return NULL;
            }
        }

        if((file=Open((char *)filename,flags))<0)
        {
            SetAmiSSLerrno(__io2errno(IoErr()));
            return NULL;
        }

#ifdef __amigaos4__
        if(append && !ChangeFilePosition(file,0,SEEK_END))
#else
        if(append && Seek(file,0,SEEK_END)<0)
#endif
        {
            SetAmiSSLerrno(__io2errno(IoErr()));
            return NULL;
        }

        TOFILE(stream)->_flag &= ~(_IOLBF);
        if(IsInteractive(file))
            TOFILE(stream)->_flag |= _IOLBF; /* set linebuffered flag */

        TOFILE(stream)->_file=file;
    }

    return stream;
}

FILE *fopen(const char *name, const char *mode)
{
    struct filenode *node;
    if((node=(struct filenode *)malloc(sizeof(struct filenode)))!=NULL)
    {
        memset(node,0,sizeof(struct filenode));
        if((node->FILE._base = (unsigned char *)malloc(BUFSIZ))!=NULL)
        {
            node->FILE._size=BUFSIZ;
            node->FILE._ptr = node->FILE._base;
            /* FIXME: what is this for? 0x80 is _IORW, nothing related to malloc */
            /* node->FILE._flag|=0x80; *//* Buffer is malloc'ed */
            node->FILE._flag |= _IOALLOCBUF;
            if(freopen(name,mode,(FILE *)&node->FILE)!=NULL)
            {
                LOCK_OBTAIN(__filelist_cs);
                AddHead((struct List *)&__filelist,(struct Node *)&node->node);
                LOCK_RELEASE(__filelist_cs);
                return (FILE *)&node->FILE;
            }
            free(node->FILE._base);
        }
        else
        {
            SetAmiSSLerrno(ENOMEM);
        }
        free(node);
    }
    else
    {
        SetAmiSSLerrno(ENOMEM);
    }
    return NULL;
}

int fclose(FILE *file)
{
    struct filenode *node;
    fflush(file);

    node = (struct filenode *)(((BYTE *)file)-offsetof(struct filenode,FILE));

    LOCK_OBTAIN(__filelist_cs);
    Remove((struct Node *)node);
    LOCK_RELEASE(__filelist_cs);

    Close(TOFILE(file)->_file);

    if (TOFILE(file)->_flag & _IOALLOCBUF)
        free(TOFILE(file)->_base);

    free(node);
    return 0;
}

int fseek(FILE *file, LONG pos, int mode)
{
#ifdef __amigaos4__
    int res = -1;
    int64 res64;
    fflush(file);
    res64 = GetFilePosition(TOFILE(file)->_file);
    if((res64!=-1LL) && ChangeFilePosition(TOFILE(file)->_file, (int64)pos, mode))
    {
        res = (int)res64;
    }
#else
    int res;
    fflush(file);
    res = Seek(TOFILE(file)->_file, pos, mode);
#endif
    if(res==-1)
    {
        SetAmiSSLerrno(__io2errno(IoErr()));
    }
    return res;
}

/* Only used by the (currently) unsupported FD interface */

int open(UNUSED const char *path_name, UNUSED int open_flag, ... /* mode_t mode */ )
{
    return(-1);
}

int close(UNUSED int fd)
{
    SetAmiSSLerrno(EINVAL);

    return(-1);
}

off_t lseek(UNUSED int fd, UNUSED off_t offset, UNUSED int mode)
{
    SetAmiSSLerrno(EINVAL);

    return(-1);
}

int read(UNUSED int fd, UNUSED void *buffer, UNUSED size_t num_bytes)
{
    SetAmiSSLerrno(EINVAL);

    return(-1);
}

int write(UNUSED int fd, UNUSED const void* buffer, UNUSED size_t num_bytes)
{
    SetAmiSSLerrno(EINVAL);

    return(-1);
}

/*
 * $Id$
 *
 * :ts=4
 *
 * Portable ISO 'C' (1994) runtime library for the Amiga computer
 * Copyright (c) 2002-2005 by Olaf Barthel <olsen@sourcery.han.de>
 * 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.
 */

int
setvbuf(FILE *stream,char *buf,int bufmode,size_t size)
{
    struct __iobuf *file = TOFILE(stream);
    char *new_buffer = NULL;
    int result = EOF;

    if ((int)size < 0)
    {
        SetAmiSSLerrno(EINVAL);
        goto out;
    }

    if (fflush(stream) == EOF)
        goto out;

    if (size == 0)
        bufmode = _IONBF; /* A buffer size of 0 bytes defaults to unbuffered operation. */
    else if (buf == NULL)
    {
        if ((new_buffer = malloc(size)) == NULL)
        {
            SetAmiSSLerrno(ENOMEM);
            goto out;
        }
    }

    /* Get rid of any buffer specially allocated for this stream. */
    if (file->_flag & _IOALLOCBUF)
    {
        free(file->_base);
        file->_base = NULL;
        file->_flag &= ~_IOALLOCBUF;
    }

    if (bufmode == _IONBF)
    {
        file->_base = &file->_cbuff;
        file->_size = 1;
    }
    else if (buf)
    {
        file->_base = (unsigned char *)buf;
        file->_size = size;
    }
    else
    {
        file->_base = (unsigned char *)new_buffer;
        file->_size = size;
        file->_flag |= _IOALLOCBUF;
    }

    file->_flag &= ~_IOBFMASK;
    file->_flag |= bufmode;

    new_buffer = NULL;

    result = 0;

 out:

    if(new_buffer != NULL)
        free(new_buffer);

    return(result);
}

void
setbuf(FILE *stream,char *buf)
{
    if(buf == NULL)
        setvbuf(stream,NULL,_IONBF,0);
    else
        setvbuf(stream,buf,_IOFBF,BUFSIZ);
}