nasmlib: split file.c into file.c and fileio.c; remove file.h

file.h was only included from file.c; combine the two and declare
functions not used anywhere else as static.

Split out the checking I/O routines into a separate routine fileio.c
as they are (mostly) not host operating system specific, whereas
file.c is mostly host operating system generalization code.

Signed-off-by: H. Peter Anvin (Intel) <hpa@zytor.com>
This commit is contained in:
H. Peter Anvin (Intel) 2025-12-14 17:47:47 -08:00
parent 5dfcfc8cab
commit 795daf3d2d
6 changed files with 264 additions and 284 deletions

View file

@ -1,77 +1,40 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/* Copyright 1996-2017 The NASM Authors - All Rights Reserved */
#include "file.h"
#include "compiler.h"
#include "nasmlib.h"
#include "error.h"
void nasm_read(void *ptr, size_t size, FILE *f)
{
size_t n = fread(ptr, 1, size, f);
if (ferror(f)) {
nasm_fatal("unable to read input: %s", strerror(errno));
} else if (n != size || feof(f)) {
nasm_fatal("fatal short read on input");
}
}
void nasm_write(const void *ptr, size_t size, FILE *f)
{
size_t n = fwrite(ptr, 1, size, f);
if (n != size || ferror(f) || feof(f))
nasm_fatal("unable to write output: %s", strerror(errno));
}
void fwriteint16_t(uint16_t data, FILE * fp)
{
data = htole16(data);
nasm_write(&data, 2, fp);
}
void fwriteint32_t(uint32_t data, FILE * fp)
{
data = htole32(data);
nasm_write(&data, 4, fp);
}
void fwriteint64_t(uint64_t data, FILE * fp)
{
data = htole64(data);
nasm_write(&data, 8, fp);
}
void fwriteaddr(uint64_t data, int size, FILE * fp)
{
data = htole64(data);
nasm_write(&data, size, fp);
}
void fwritezero(off_t bytes, FILE *fp)
{
size_t blksize;
#ifdef os_ftruncate
if (bytes >= BUFSIZ && !ferror(fp) && !feof(fp)) {
off_t pos = ftello(fp);
if (pos != (off_t)-1) {
off_t end = pos + bytes;
if (!fflush(fp) && !os_ftruncate(fileno(fp), end)) {
fseeko(fp, 0, SEEK_END);
pos = ftello(fp);
if (pos != (off_t)-1)
bytes = end - pos; /* This SHOULD be zero */
}
}
}
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_IO_H
# include <io.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_SYS_MMAN_H
# include <sys/mman.h>
#endif
while (bytes > 0) {
blksize = (bytes < ZERO_BUF_SIZE) ? bytes : ZERO_BUF_SIZE;
#ifndef R_OK
# define R_OK 4 /* Classic Unix constant, same on Windows */
#endif
nasm_write(zero_buffer, blksize, fp);
bytes -= blksize;
}
}
#ifdef _WIN32
#ifdef S_ISREG
/* all good */
#elif defined(HAVE_S_ISREG)
/* exists, but not a macro */
# define S_ISREG S_ISREG
#elif defined(S_IFMT) && defined(S_IFREG)
# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#elif defined(_S_IFMT) && defined(_S_IFREG)
# define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG)
#endif
/*
* On Windows, we want to use _wfopen(), as fopen() has a much smaller limit
@ -83,8 +46,13 @@ void fwritezero(off_t bytes, FILE *fp)
* apparently Windows 10 contains a registry option to override this
* limit anyway... but only for the wide character interfaces.
*/
#ifdef _WIN32
#include <wchar.h>
os_filename os_mangle_filename(const char *filename)
typedef wchar_t *os_filename;
typedef wchar_t os_fopenflag;
static os_filename os_mangle_filename(const char *filename)
{
size_t wclen;
wchar_t *buf;
@ -105,6 +73,131 @@ os_filename os_mangle_filename(const char *filename)
return buf;
}
static inline void os_free_filename(os_filename filename)
{
nasm_free(filename);
}
# define os_fopen _wfopen
# define os_access _waccess
/*
* On Win32/64, we have to use the _wstati64() function. Note that
* we can't use _wstat64() without depending on a needlessly new
* version os MSVCRT.
*/
typedef struct _stati64 os_struct_stat;
# define os_stat _wstati64
# define os_fstat _fstati64
static inline void os_set_binary_mode(FILE *f) {
int ret = _setmode(_fileno(f), _O_BINARY);
if (ret == -1) {
nasm_fatalf(ERR_NOFILE, "unable to set file mode to binary: %s",
strerror(errno));
}
}
#else /* not _WIN32 */
typedef const char *os_filename;
typedef char os_fopenflag;
static inline os_filename os_mangle_filename(const char *filename)
{
return filename;
}
static inline void os_free_filename(os_filename filename)
{
(void)filename; /* Nothing to do */
}
static inline void os_set_binary_mode(FILE *f) {
(void)f;
}
# define os_fopen fopen
#if defined(HAVE_FACCESSAT) && defined(AT_EACCESS)
static inline int os_access(os_filename pathname, int mode)
{
return faccessat(AT_FDCWD, pathname, mode, AT_EACCESS);
}
# define os_access os_access
#elif defined(HAVE_ACCESS)
# define os_access access
#endif
#ifdef HAVE_STRUCT_STAT
typedef struct stat os_struct_stat;
# ifdef HAVE_STAT
# define os_stat stat
# endif
# ifdef HAVE_FSTAT
# define os_fstat fstat
# endif
#else
struct dummy_struct_stat {
int st_mode;
int st_size;
};
typedef struct dummy_struct_stat os_struct_stat;
#endif
#endif /* Not _WIN32 */
#ifdef fileno
/* all good */
#elif defined(HAVE_FILENO)
/* exists, but not a macro */
# define fileno fileno
#elif defined(_fileno) || defined(HAVE__FILENO)
# define fileno _fileno
#endif
#ifndef S_ISREG
# undef os_stat
# undef os_fstat
#endif
/* Disable these functions if they don't support something we need */
#ifndef fileno
# undef os_fstat
# undef os_ftruncate
# undef HAVE_MMAP
#endif
/*
* If we don't have functional versions of these functions,
* stub them out so we don't need so many #ifndefs
*/
#ifndef os_stat
static inline int os_stat(os_filename osfname, os_struct_stat *st)
{
(void)osfname;
(void)st;
return -1;
}
#endif
#ifndef os_fstat
static inline int os_fstat(int fd, os_struct_stat *st)
{
(void)fd;
(void)st;
return -1;
}
#endif
#ifndef S_ISREG
static inline bool S_ISREG(int m)
{
(void)m;
return false;
}
#endif
void nasm_set_binary_mode(FILE *f)

View file

@ -1,204 +0,0 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/* Copyright 1996-2022 The NASM Authors - All Rights Reserved */
#ifndef NASMLIB_FILE_H
#define NASMLIB_FILE_H
#include "compiler.h"
#include "nasmlib.h"
#include "error.h"
#include <errno.h>
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif
#ifdef HAVE_SYS_TYPES_H
#endif
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif
#ifdef HAVE_IO_H
# include <io.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE_SYS_MMAN_H
# include <sys/mman.h>
#endif
#ifndef R_OK
# define R_OK 4 /* Classic Unix constant, same on Windows */
#endif
/* Can we adjust the file size without actually writing all the bytes? */
#ifdef HAVE__CHSIZE_S
# define os_ftruncate(fd,size) _chsize_s(fd,size)
#elif defined(HAVE__CHSIZE)
# define os_ftruncate(fd,size) _chsize(fd,size)
#elif defined(HAVE_FTRUNCATE)
# define os_ftruncate(fd,size) ftruncate(fd,size)
#endif
/*
* On Windows, we want to use _wfopen(), as fopen() has a much smaller limit
* on the path length that it supports. Furthermore, we want to prefix the
* path name with \\?\ in order to let the Windows kernel know that
* we are not limited to PATH_MAX characters. Thus, we wrap all the functions
* which take filenames...
*/
#ifdef _WIN32
# include <wchar.h>
typedef wchar_t *os_filename;
typedef wchar_t os_fopenflag;
os_filename os_mangle_filename(const char *filename);
static inline void os_free_filename(os_filename filename)
{
nasm_free(filename);
}
# define os_fopen _wfopen
# define os_access _waccess
/*
* On Win32/64, we have to use the _wstati64() function. Note that
* we can't use _wstat64() without depending on a needlessly new
* version os MSVCRT.
*/
typedef struct _stati64 os_struct_stat;
# define os_stat _wstati64
# define os_fstat _fstati64
/*
* On Win32/64, freopen() and _wfreopen() fails when the mode string
* is with the letter 'b' that represents to set binary mode. On
* POSIX operating systems, the 'b' is ignored, without failure.
*/
#include <io.h>
#include <fcntl.h>
static inline void os_set_binary_mode(FILE *f) {
int ret = _setmode(_fileno(f), _O_BINARY);
if (ret == -1) {
nasm_fatalf(ERR_NOFILE, "unable to open file: %s",
strerror(errno));
}
}
#else /* not _WIN32 */
typedef const char *os_filename;
typedef char os_fopenflag;
static inline os_filename os_mangle_filename(const char *filename)
{
return filename;
}
static inline void os_free_filename(os_filename filename)
{
(void)filename; /* Nothing to do */
}
static inline void os_set_binary_mode(FILE *f) {
(void)f;
}
# define os_fopen fopen
#if defined(HAVE_FACCESSAT) && defined(AT_EACCESS)
static inline int os_access(os_filename pathname, int mode)
{
return faccessat(AT_FDCWD, pathname, mode, AT_EACCESS);
}
# define os_access os_access
#elif defined(HAVE_ACCESS)
# define os_access access
#endif
#ifdef HAVE_STRUCT_STAT
typedef struct stat os_struct_stat;
# ifdef HAVE_STAT
# define os_stat stat
# endif
# ifdef HAVE_FSTAT
# define os_fstat fstat
# endif
#else
struct dummy_struct_stat {
int st_mode;
int st_size;
};
typedef struct dummy_struct_stat os_struct_stat;
#endif
#endif /* Not _WIN32 */
#ifdef S_ISREG
/* all good */
#elif defined(HAVE_S_ISREG)
/* exists, but not a macro */
# define S_ISREG S_ISREG
#elif defined(S_IFMT) && defined(S_IFREG)
# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#elif defined(_S_IFMT) && defined(_S_IFREG)
# define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG)
#endif
#ifdef fileno
/* all good */
#elif defined(HAVE_FILENO)
/* exists, but not a macro */
# define fileno fileno
#elif defined(_fileno) || defined(HAVE__FILENO)
# define fileno _fileno
#endif
#ifndef S_ISREG
# undef os_stat
# undef os_fstat
#endif
/* Disable these functions if they don't support something we need */
#ifndef fileno
# undef os_fstat
# undef os_ftruncate
# undef HAVE_MMAP
#endif
/*
* If we don't have functional versions of these functions,
* stub them out so we don't need so many #ifndefs
*/
#ifndef os_stat
static inline int os_stat(os_filename osfname, os_struct_stat *st)
{
(void)osfname;
(void)st;
return -1;
}
#endif
#ifndef os_fstat
static inline int os_fstat(int fd, os_struct_stat *st)
{
(void)fd;
(void)st;
return -1;
}
#endif
#ifndef S_ISREG
static inline bool S_ISREG(int m)
{
(void)m;
return false;
}
#endif
#endif /* NASMLIB_FILE_H */

91
nasmlib/fileio.c Normal file
View file

@ -0,0 +1,91 @@
/* SPDX-License-Identifier: BSD-2-Clause */
/* Copyright 1996-2017 The NASM Authors - All Rights Reserved */
#include "compiler.h"
#include "nasmlib.h"
#include "error.h"
void nasm_read(void *ptr, size_t size, FILE *f)
{
size_t n = fread(ptr, 1, size, f);
if (ferror(f)) {
nasm_fatal("unable to read input: %s", strerror(errno));
} else if (n != size || feof(f)) {
nasm_fatal("fatal short read on input");
}
}
void nasm_write(const void *ptr, size_t size, FILE *f)
{
size_t n = fwrite(ptr, 1, size, f);
if (n != size || ferror(f) || feof(f))
nasm_fatal("unable to write output: %s", strerror(errno));
}
void fwriteint16_t(uint16_t data, FILE * fp)
{
data = htole16(data);
nasm_write(&data, 2, fp);
}
void fwriteint32_t(uint32_t data, FILE * fp)
{
data = htole32(data);
nasm_write(&data, 4, fp);
}
void fwriteint64_t(uint64_t data, FILE * fp)
{
data = htole64(data);
nasm_write(&data, 8, fp);
}
void fwriteaddr(uint64_t data, int size, FILE * fp)
{
data = htole64(data);
nasm_write(&data, size, fp);
}
/* Can we adjust the file size without actually writing all the bytes? */
#ifdef HAVE_IO_H
# include <io.h>
#endif
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#ifdef HAVE__CHSIZE_S
# define os_ftruncate(fd,size) _chsize_s(fd,size)
#elif defined(HAVE__CHSIZE)
# define os_ftruncate(fd,size) _chsize(fd,size)
#elif defined(HAVE_FTRUNCATE)
# define os_ftruncate(fd,size) ftruncate(fd,size)
#endif
void fwritezero(off_t bytes, FILE *fp)
{
size_t blksize;
#ifdef os_ftruncate
if (bytes >= BUFSIZ && !ferror(fp) && !feof(fp)) {
off_t pos = ftello(fp);
if (pos != (off_t)-1) {
off_t end = pos + bytes;
if (!fflush(fp) && !os_ftruncate(fileno(fp), end)) {
fseeko(fp, 0, SEEK_END);
pos = ftello(fp);
if (pos != (off_t)-1)
bytes = end - pos; /* This SHOULD be zero */
}
}
}
#endif
while (bytes > 0) {
blksize = (bytes < ZERO_BUF_SIZE) ? bytes : ZERO_BUF_SIZE;
nasm_write(zero_buffer, blksize, fp);
bytes -= blksize;
}
}