Skip to content

Commit

Permalink
fixed RESIZE-FILE for Cygwin (#198)
Browse files Browse the repository at this point in the history
* docu: update example for IO_SOURCE
* removed getFilePathFromStream() from freopen call
* include Minix in selecting the Unix implementation

Fixes #189
  • Loading branch information
guberathome authored Jan 21, 2025
1 parent 9db4e9e commit bb721e5
Showing 1 changed file with 49 additions and 49 deletions.
98 changes: 49 additions & 49 deletions csrc/stdio/pf_fileio_stdio.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/***************************************************************
** File access routines based on ANSI C (no Unix stuff).
** File access routines based on ANSI C
** (no more Unix stuff than strictly necessary).
**
** This file is part of pForth
**
Expand All @@ -25,32 +26,33 @@

typedef int bool_t;

/* Copy SIZE bytes from File FROM to File TO. Return non-FALSE on error. */
static bool_t CopyFile( FileStream *From, FileStream *To, long Size)
{
bool_t Error = TRUE;
size_t Diff = Size;
size_t BufSize = 512;
char *Buffer = pfAllocMem( BufSize );
if( Buffer != 0 )
{
while( Diff > 0 )
{
size_t N = MIN( Diff, BufSize );
if( fread( Buffer, 1, N, From ) < N ) goto cleanup;
if( fwrite( Buffer, 1, N, To ) < N ) goto cleanup;
Diff -= N;
}
Error = FALSE;
static bool_t TruncateFile( FileStream *File, long Newsize ); /* Shrink the file FILE to NEWSIZE. Return non-FALSE on error. */

cleanup:
pfFreeMem( Buffer );
}
return Error;
#if defined( __CYGWIN__) || defined( __FreeBSD__) || defined(__NetBSD__) || defined(__minix__) /* __unix__ */
/* Cygwin, FreeBSD, NetBSD and (Manjaro)Linux all define "__unix__",
which might also be defined on incompatible platforms as well (so we do not use it).
Linux is excluded from the if statement in order to test the portable code on build.
This uses Unix specific APIs to work around problems with the portable implementation.
*/

#include<stdio.h> /* fileno() */
#include<unistd.h> /* ftruncate */

static bool_t TruncateFile( FileStream *File, long Newsize )
{
bool_t Error = TRUE;
int fd;
if( -1 != ( fd = fileno(File) ) )
{
if( 0 == ftruncate(fd, Newsize) )
Error = FALSE;
}
return Error;
}

/* Shrink the file FILE to NEWSIZE. Return non-FALSE on error.
*
#else /* __unix__ */

/*
* There's no direct way to do this in ANSI C. The closest thing we
* have is freopen(3), which truncates a file to zero length if we use
* "w+b" as mode argument. So we do this:
Expand All @@ -64,39 +66,34 @@ static bool_t CopyFile( FileStream *From, FileStream *To, long Size)
*
* We call freopen with NULL as path argument, because we don't know
* the actual file-name. It seems that the trick with path=NULL is
* not part of C89 but it's in C99. It does not work on NetBSD though.
*/

#if defined(__NetBSD__) || defined(_NETBSD_SOURCE)
/* Tested on NetBSD 10.1.
"F_GETPATH" is not defined on Linux (Kernel 6.6.63), FreeBSD (13.2) or MSYS-Cygwin
(MSYS_NT-10.0-22631), so we restrict this function to NetBSD.
It might also work on "Mac OS X" but that needs to be verified.
* not part of C89 but it's in C99.
* It does not work on NetBSD and Cygwin though.
*/

#include<fcntl.h>

/* note: we do not malloc this, so we need not to free it after use! */
static char getFilePathFromStreamData[PATH_MAX];

static char* getFilePathFromStream( FileStream* File)
/* Copy SIZE bytes from File FROM to File TO. Return non-FALSE on error. */
static bool_t CopyFile( FileStream *From, FileStream *To, long Size)
{
char* result = NULL;
int fd;
if( (fd=fileno(File)) != -1 )
bool_t Error = TRUE;
size_t Diff = Size;
size_t BufSize = 512;
char *Buffer = pfAllocMem( BufSize );
if( Buffer != 0 )
{
if( fcntl(fd, F_GETPATH, getFilePathFromStreamData) != -1 )
while( Diff > 0 )
{
result = getFilePathFromStreamData;
size_t N = MIN( Diff, BufSize );
if( fread( Buffer, 1, N, From ) < N ) goto cleanup;
if( fwrite( Buffer, 1, N, To ) < N ) goto cleanup;
Diff -= N;
}
Error = FALSE;

cleanup:
pfFreeMem( Buffer );
}
return result;
return Error;
}

#else
static char* getFilePathFromStream( FileStream* File) { return NULL; }
#endif /* NetBSD */

static bool_t TruncateFile( FileStream *File, long Newsize )
{
bool_t Error = TRUE;
Expand All @@ -107,7 +104,7 @@ static bool_t TruncateFile( FileStream *File, long Newsize )
{
if( CopyFile( File, TmpFile, Newsize )) goto cleanup;
if( fseek( TmpFile, 0, SEEK_SET ) != 0 ) goto cleanup;
if( freopen( getFilePathFromStream(File), "w+b", File ) == NULL ) goto cleanup;
if( freopen( NULL, "w+b", File ) == NULL ) goto cleanup;
if( CopyFile( TmpFile, File, Newsize )) goto cleanup;
Error = FALSE;

Expand All @@ -118,6 +115,9 @@ static bool_t TruncateFile( FileStream *File, long Newsize )
return Error;
}

#endif /* __unix__ */


/* Write DIFF 0 bytes to FILE. Return non-FALSE on error. */
static bool_t ExtendFile( FileStream *File, size_t Diff )
{
Expand Down

0 comments on commit bb721e5

Please sign in to comment.