1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2017 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
36 void nasm_read(void *ptr
, size_t size
, FILE *f
)
38 size_t n
= fread(ptr
, 1, size
, f
);
40 nasm_fatal("unable to read input: %s", strerror(errno
));
41 } else if (n
!= size
|| feof(f
)) {
42 nasm_fatal("fatal short read on input");
46 void nasm_write(const void *ptr
, size_t size
, FILE *f
)
48 size_t n
= fwrite(ptr
, 1, size
, f
);
49 if (n
!= size
|| ferror(f
) || feof(f
))
50 nasm_fatal("unable to write output: %s", strerror(errno
));
53 void fwriteint16_t(uint16_t data
, FILE * fp
)
55 data
= cpu_to_le16(data
);
56 nasm_write(&data
, 2, fp
);
59 void fwriteint32_t(uint32_t data
, FILE * fp
)
61 data
= cpu_to_le32(data
);
62 nasm_write(&data
, 4, fp
);
65 void fwriteint64_t(uint64_t data
, FILE * fp
)
67 data
= cpu_to_le64(data
);
68 nasm_write(&data
, 8, fp
);
71 void fwriteaddr(uint64_t data
, int size
, FILE * fp
)
73 data
= cpu_to_le64(data
);
74 nasm_write(&data
, size
, fp
);
77 void fwritezero(off_t bytes
, FILE *fp
)
82 if (bytes
>= BUFSIZ
&& !ferror(fp
) && !feof(fp
)) {
83 off_t pos
= ftello(fp
);
84 if (pos
!= (off_t
)-1) {
85 off_t end
= pos
+ bytes
;
86 if (!fflush(fp
) && !os_ftruncate(fileno(fp
), end
)) {
87 fseeko(fp
, 0, SEEK_END
);
90 bytes
= end
- pos
; /* This SHOULD be zero */
97 blksize
= (bytes
< ZERO_BUF_SIZE
) ? bytes
: ZERO_BUF_SIZE
;
99 nasm_write(zero_buffer
, blksize
, fp
);
107 * On Windows, we want to use _wfopen(), as fopen() has a much smaller limit
108 * on the path length that it supports.
110 * Previously we tried to prefix the path name with \\?\ in order to
111 * let the Windows kernel know that we are not limited to PATH_MAX
112 * characters, but it breaks relative paths among other things, and
113 * apparently Windows 10 contains a registry option to override this
114 * limit anyway. One day maybe they will even implement UTF-8 as byte
115 * characters so we can use the standard file API even on this OS.
118 os_filename
os_mangle_filename(const char *filename
)
126 * Note: mbsrtowcs() return (size_t)-1 on error, otherwise
127 * the length of the string *without* final NUL in wchar_t
128 * units. Thus we add 1 for the final NUL; the error value
131 memset(&ps
, 0, sizeof ps
); /* Begin in the initial state */
133 wclen
= mbsrtowcs(NULL
, &p
, 0, &ps
) + 1;
137 buf
= nasm_malloc(wclen
* sizeof(wchar_t));
139 memset(&ps
, 0, sizeof ps
); /* Begin in the initial state */
141 if (mbsrtowcs(buf
, &p
, wclen
, &ps
) + 1 != wclen
|| p
) {
151 FILE *nasm_open_read(const char *filename
, enum file_flags flags
)
156 osfname
= os_mangle_filename(filename
);
158 os_fopenflag fopen_flags
[4];
159 memset(fopen_flags
, 0, sizeof fopen_flags
);
161 fopen_flags
[0] = 'r';
162 fopen_flags
[1] = (flags
& NF_TEXT
) ? 't' : 'b';
164 #if defined(__GLIBC__) || defined(__linux__)
166 * Try to open this file with memory mapping for speed, unless we are
167 * going to do it "manually" with nasm_map_file()
169 if (!(flags
& NF_FORMAP
))
170 fopen_flags
[2] = 'm';
174 f
= os_fopen(osfname
, fopen_flags
);
175 if (f
|| errno
!= EINVAL
|| !fopen_flags
[2])
178 /* We got EINVAL but with 'm'; try again without 'm' */
179 fopen_flags
[2] = '\0';
182 os_free_filename(osfname
);
185 if (!f
&& (flags
& NF_FATAL
))
186 nasm_fatalf(ERR_NOFILE
, "unable to open input file: `%s': %s",
187 filename
, strerror(errno
));
192 FILE *nasm_open_write(const char *filename
, enum file_flags flags
)
197 osfname
= os_mangle_filename(filename
);
199 os_fopenflag fopen_flags
[3];
201 fopen_flags
[0] = 'w';
202 fopen_flags
[1] = (flags
& NF_TEXT
) ? 't' : 'b';
203 fopen_flags
[2] = '\0';
205 f
= os_fopen(osfname
, fopen_flags
);
206 os_free_filename(osfname
);
209 if (!f
&& (flags
& NF_FATAL
))
210 nasm_fatalf(ERR_NOFILE
, "unable to open output file: `%s': %s",
211 filename
, strerror(errno
));
216 /* The appropriate "rb" strings for os_fopen() */
217 static const os_fopenflag fopenflags_rb
[3] = { 'r', 'b', 0 };
220 * Report the existence of a file
222 bool nasm_file_exists(const char *filename
)
230 osfname
= os_mangle_filename(filename
);
235 exists
= os_access(osfname
, R_OK
) == 0;
237 f
= os_fopen(osfname
, fopenflags_rb
);
243 os_free_filename(osfname
);
248 * Report the file size of an open file. This MAY move the file pointer.
250 off_t
nasm_file_size(FILE *f
)
255 if (!os_fstat(fileno(f
), &st
) && S_ISREG(st
.st_mode
))
258 /* Do it the hard way... this tests for seekability */
260 if (fseeko(f
, 0, SEEK_CUR
))
261 goto fail
; /* Not seekable, don't even try */
264 if (where
== (off_t
)-1)
267 if (fseeko(f
, 0, SEEK_END
))
271 if (end
== (off_t
)-1)
275 * Move the file pointer back. If this fails, this is probably
278 if (fseeko(f
, where
, SEEK_SET
))
288 * Report file size given pathname
290 off_t
nasm_file_size_by_path(const char *pathname
)
297 osfname
= os_mangle_filename(pathname
);
299 if (!os_stat(osfname
, &st
) && S_ISREG(st
.st_mode
))
302 fp
= os_fopen(osfname
, fopenflags_rb
);
304 len
= nasm_file_size(fp
);
312 * Report the timestamp on a file, returns true if successful
314 bool nasm_file_time(time_t *t
, const char *pathname
)
321 osfname
= os_mangle_filename(pathname
);
325 rv
= !os_stat(osfname
, &st
);
327 os_free_filename(osfname
);
331 return false; /* No idea how to do this on this OS */