blob: 51f07309d7cfbaa2b677db66b7b6255ff5c3e53a [file] [log] [blame]
H. Peter Anvinbdae10b2016-03-08 01:22:13 -08001/* ----------------------------------------------------------------------- *
2 *
H. Peter Anvincbd72b62017-02-23 18:19:25 -08003 * Copyright 1996-2017 The NASM Authors - All Rights Reserved
H. Peter Anvinbdae10b2016-03-08 01:22:13 -08004 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
10 *
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.
17 *
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.
31 *
32 * ----------------------------------------------------------------------- */
33
H. Peter Anvin92223642017-02-23 18:39:00 -080034#include "file.h"
H. Peter Anvin397c1692016-10-04 17:01:59 -070035
H. Peter Anvin8dc96532017-04-17 13:52:19 -070036void nasm_read(void *ptr, size_t size, FILE *f)
37{
38 size_t n = fread(ptr, 1, size, f);
39 if (ferror(f)) {
40 nasm_fatal(0, "unable to read input: %s", strerror(errno));
41 } else if (n != size || feof(f)) {
42 nasm_fatal(0, "fatal short read on input");
43 }
44}
45
H. Peter Anvinbdae10b2016-03-08 01:22:13 -080046void nasm_write(const void *ptr, size_t size, FILE *f)
47{
48 size_t n = fwrite(ptr, 1, size, f);
49 if (n != size || ferror(f) || feof(f))
50 nasm_fatal(0, "unable to write output: %s", strerror(errno));
51}
52
53#ifdef WORDS_LITTLEENDIAN
54
55void fwriteint16_t(uint16_t data, FILE * fp)
56{
57 nasm_write(&data, 2, fp);
58}
59
60void fwriteint32_t(uint32_t data, FILE * fp)
61{
62 nasm_write(&data, 4, fp);
63}
64
65void fwriteint64_t(uint64_t data, FILE * fp)
66{
67 nasm_write(&data, 8, fp);
68}
69
70void fwriteaddr(uint64_t data, int size, FILE * fp)
71{
72 nasm_write(&data, size, fp);
73}
74
75#else /* not WORDS_LITTLEENDIAN */
76
77void fwriteint16_t(uint16_t data, FILE * fp)
78{
79 char buffer[2], *p = buffer;
80 WRITESHORT(p, data);
81 nasm_write(buffer, 2, fp);
82}
83
84void fwriteint32_t(uint32_t data, FILE * fp)
85{
86 char buffer[4], *p = buffer;
87 WRITELONG(p, data);
88 nasm_write(buffer, 4, fp);
89}
90
91void fwriteint64_t(uint64_t data, FILE * fp)
92{
93 char buffer[8], *p = buffer;
94 WRITEDLONG(p, data);
95 nasm_write(buffer, 8, fp);
96}
97
98void fwriteaddr(uint64_t data, int size, FILE * fp)
99{
100 char buffer[8], *p = buffer;
101 WRITEADDR(p, data, size);
102 nasm_write(buffer, size, fp);
103}
104
105#endif
106
107
H. Peter Anvind81a2352016-09-21 14:03:18 -0700108void fwritezero(off_t bytes, FILE *fp)
H. Peter Anvinbdae10b2016-03-08 01:22:13 -0800109{
110 size_t blksize;
111
112#ifdef nasm_ftruncate
113 if (bytes >= BUFSIZ && !ferror(fp) && !feof(fp)) {
114 off_t pos = ftello(fp);
115 if (pos >= 0) {
H. Peter Anvind81a2352016-09-21 14:03:18 -0700116 pos += bytes;
H. Peter Anvinbdae10b2016-03-08 01:22:13 -0800117 if (!fflush(fp) &&
H. Peter Anvind81a2352016-09-21 14:03:18 -0700118 !nasm_ftruncate(fileno(fp), pos) &&
119 !fseeko(fp, pos, SEEK_SET))
H. Peter Anvinbdae10b2016-03-08 01:22:13 -0800120 return;
121 }
122 }
123#endif
124
H. Peter Anvind81a2352016-09-21 14:03:18 -0700125 while (bytes > 0) {
H. Peter Anvinbdae10b2016-03-08 01:22:13 -0800126 blksize = (bytes < ZERO_BUF_SIZE) ? bytes : ZERO_BUF_SIZE;
127
128 nasm_write(zero_buffer, blksize, fp);
129 bytes -= blksize;
130 }
131}
H. Peter Anvin3e83cec2016-05-25 04:28:46 -0700132
H. Peter Anvin3e83cec2016-05-25 04:28:46 -0700133FILE *nasm_open_read(const char *filename, enum file_flags flags)
134{
Chang S. Bae54317322017-04-16 20:24:39 -0700135 FILE *f = NULL;
H. Peter Anvind81a2352016-09-21 14:03:18 -0700136 bool again = true;
H. Peter Anvin3e83cec2016-05-25 04:28:46 -0700137
H. Peter Anvind81a2352016-09-21 14:03:18 -0700138#ifdef __GLIBC__
139 /*
140 * Try to open this file with memory mapping for speed, unless we are
141 * going to do it "manually" with nasm_map_file()
142 */
143 if (!(flags & NF_FORMAP)) {
144 f = fopen(filename, (flags & NF_TEXT) ? "rtm" : "rbm");
145 again = (!f) && (errno == EINVAL); /* Not supported, try without m */
146 }
147#endif
148
149 if (again)
150 f = fopen(filename, (flags & NF_TEXT) ? "rt" : "rb");
151
H. Peter Anvin3e83cec2016-05-25 04:28:46 -0700152 if (!f && (flags & NF_FATAL))
153 nasm_fatal(ERR_NOFILE, "unable to open input file: `%s': %s",
154 filename, strerror(errno));
155
156 return f;
157}
158
159FILE *nasm_open_write(const char *filename, enum file_flags flags)
160{
161 FILE *f;
162
H. Peter Anvind81a2352016-09-21 14:03:18 -0700163 f = fopen(filename, (flags & NF_TEXT) ? "wt" : "wb");
164
H. Peter Anvin3e83cec2016-05-25 04:28:46 -0700165 if (!f && (flags & NF_FATAL))
166 nasm_fatal(ERR_NOFILE, "unable to open output file: `%s': %s",
167 filename, strerror(errno));
168
169 return f;
170}
H. Peter Anvinc1700892016-09-20 18:26:42 -0700171
H. Peter Anvind81a2352016-09-21 14:03:18 -0700172/*
173 * Report the existence of a file
174 */
175bool nasm_file_exists(const char *filename)
176{
177#if defined(HAVE_FACCESSAT) && defined(AT_EACCESS)
178 return faccessat(AT_FDCWD, filename, R_OK, AT_EACCESS) == 0;
179#elif defined(HAVE_ACCESS)
180 return access(filename, R_OK) == 0;
181#else
182 FILE *f;
183
184 f = fopen(filename, "rb");
185 if (f) {
186 fclose(f);
187 return true;
188 } else {
189 return false;
190 }
191#endif
192}
193
194/*
195 * Report file size. This MAY move the file pointer.
196 */
197off_t nasm_file_size(FILE *f)
198{
H. Peter Anvin31184292017-04-06 15:30:56 -0700199#ifdef HAVE__FILELENGTHI64
H. Peter Anvin397c1692016-10-04 17:01:59 -0700200 return _filelengthi64(fileno(f));
H. Peter Anvincbd72b62017-02-23 18:19:25 -0800201#elif defined(nasm_fstat)
H. Peter Anvin31184292017-04-06 15:30:56 -0700202 nasm_struct_stat st;
H. Peter Anvind81a2352016-09-21 14:03:18 -0700203
H. Peter Anvincbd72b62017-02-23 18:19:25 -0800204 if (nasm_fstat(fileno(f), &st))
H. Peter Anvind81a2352016-09-21 14:03:18 -0700205 return (off_t)-1;
206
207 return st.st_size;
208#else
209 if (fseeko(f, 0, SEEK_END))
210 return (off_t)-1;
211
212 return ftello(f);
213#endif
214}
215
216/*
217 * Report file size given pathname
218 */
219off_t nasm_file_size_by_path(const char *pathname)
220{
H. Peter Anvin675e7b72017-04-05 21:19:03 -0700221#ifdef nasm_stat
H. Peter Anvin31184292017-04-06 15:30:56 -0700222 nasm_struct_stat st;
H. Peter Anvind81a2352016-09-21 14:03:18 -0700223
H. Peter Anvin675e7b72017-04-05 21:19:03 -0700224 if (nasm_stat(pathname, &st))
H. Peter Anvind81a2352016-09-21 14:03:18 -0700225 return (off_t)-1;
226
227 return st.st_size;
228#else
229 FILE *fp;
230 off_t len;
231
232 fp = nasm_open_read(pathname, NF_BINARY);
233 if (!fp)
234 return (off_t)-1;
235
236 len = nasm_file_size(fp);
237 fclose(fp);
238
239 return len;
240#endif
241}
H. Peter Anvina771be82017-08-16 14:53:18 -0700242
243/*
244 * Report the timestamp on a file, returns true if successful
245 */
246bool nasm_file_time(time_t *t, const char *pathname)
247{
248#ifdef nasm_stat
249 nasm_struct_stat st;
250
251 if (nasm_stat(pathname, &st))
252 return false;
253
254 *t = st.st_mtime;
255 return true;
256#else
257 return false; /* No idea how to do this on this OS */
258#endif
259}