1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
|
/* fopen( const char *, const char * )
This file is part of the Public Domain C Library (PDCLib).
Permission is granted to use, modify, and / or redistribute at will.
*/
#include <stdio.h>
#include <stdlib.h>
#ifndef REGTEST
#include "pdclib/_PDCLIB_glue.h"
#include <string.h>
#ifndef __STDC_NO_THREADS__
#include <threads.h>
extern mtx_t _PDCLIB_filelist_mtx;
#endif
extern struct _PDCLIB_file_t * _PDCLIB_filelist;
struct _PDCLIB_file_t * fopen( const char * _PDCLIB_restrict filename, const char * _PDCLIB_restrict mode )
{
struct _PDCLIB_file_t * rc;
unsigned int filemode = _PDCLIB_filemode( mode );
if ( filemode == 0 )
{
/* mode invalid */
return NULL;
}
if ( filename == NULL || filename[0] == '\0' )
{
/* filename invalid */
return NULL;
}
/* See tmpfile(), which does much of the same. */
if ( ( rc = _PDCLIB_init_file_t( NULL ) ) == NULL )
{
/* initializing FILE structure failed */
return NULL;
}
/* Setting buffer to _IOLBF because "when opened, a stream is fully
buffered if and only if it can be determined not to refer to an
interactive device."
*/
rc->status |= filemode | _IOLBF;
if ( ( rc->handle = _PDCLIB_open( filename, rc->status ) ) == _PDCLIB_NOHANDLE )
{
/* OS open() failed */
#ifndef __STDC_NO_THREADS
mtx_destroy( &rc->mtx );
#endif
free( rc->buffer );
free( rc );
return NULL;
}
/* Getting absolute filename (for potential freopen()) */
rc->filename = _PDCLIB_realpath( filename );
/* Adding to list of open files */
_PDCLIB_LOCK( _PDCLIB_filelist_mtx );
rc->next = _PDCLIB_filelist;
_PDCLIB_filelist = rc;
_PDCLIB_UNLOCK( _PDCLIB_filelist_mtx );
return rc;
}
#endif
#ifdef TEST
#include "_PDCLIB_test.h"
int main( void )
{
/* Some of the tests are not executed for regression tests, as the libc on
my system is at once less forgiving (segfaults on mode NULL) and more
forgiving (accepts undefined modes).
*/
FILE * fh;
remove( testfile );
TESTCASE_NOREG( fopen( NULL, NULL ) == NULL );
TESTCASE( fopen( NULL, "w" ) == NULL );
TESTCASE_NOREG( fopen( "", NULL ) == NULL );
TESTCASE( fopen( "", "w" ) == NULL );
TESTCASE( fopen( testfile, "" ) == NULL );
TESTCASE_NOREG( fopen( testfile, "wq" ) == NULL ); /* Undefined mode */
TESTCASE_NOREG( fopen( testfile, "wr" ) == NULL ); /* Undefined mode */
TESTCASE( ( fh = fopen( testfile, "w" ) ) != NULL );
TESTCASE( fclose( fh ) == 0 );
TESTCASE( remove( testfile ) == 0 );
return TEST_RESULTS;
}
#endif
|