blob: 93d611179350d0602f42eedfba81a948dfb81c8d [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 Anvinbdae10b2016-03-08 01:22:13 -080036void nasm_write(const void *ptr, size_t size, FILE *f)
37{
38 size_t n = fwrite(ptr, 1, size, f);
39 if (n != size || ferror(f) || feof(f))
40 nasm_fatal(0, "unable to write output: %s", strerror(errno));
41}
42
43#ifdef WORDS_LITTLEENDIAN
44
45void fwriteint16_t(uint16_t data, FILE * fp)
46{
47 nasm_write(&data, 2, fp);
48}
49
50void fwriteint32_t(uint32_t data, FILE * fp)
51{
52 nasm_write(&data, 4, fp);
53}
54
55void fwriteint64_t(uint64_t data, FILE * fp)
56{
57 nasm_write(&data, 8, fp);
58}
59
60void fwriteaddr(uint64_t data, int size, FILE * fp)
61{
62 nasm_write(&data, size, fp);
63}
64
65#else /* not WORDS_LITTLEENDIAN */
66
67void fwriteint16_t(uint16_t data, FILE * fp)
68{
69 char buffer[2], *p = buffer;
70 WRITESHORT(p, data);
71 nasm_write(buffer, 2, fp);
72}
73
74void fwriteint32_t(uint32_t data, FILE * fp)
75{
76 char buffer[4], *p = buffer;
77 WRITELONG(p, data);
78 nasm_write(buffer, 4, fp);
79}
80
81void fwriteint64_t(uint64_t data, FILE * fp)
82{
83 char buffer[8], *p = buffer;
84 WRITEDLONG(p, data);
85 nasm_write(buffer, 8, fp);
86}
87
88void fwriteaddr(uint64_t data, int size, FILE * fp)
89{
90 char buffer[8], *p = buffer;
91 WRITEADDR(p, data, size);
92 nasm_write(buffer, size, fp);
93}
94
95#endif
96
97
H. Peter Anvind81a2352016-09-21 14:03:18 -070098void fwritezero(off_t bytes, FILE *fp)
H. Peter Anvinbdae10b2016-03-08 01:22:13 -080099{
100 size_t blksize;
101
102#ifdef nasm_ftruncate
103 if (bytes >= BUFSIZ && !ferror(fp) && !feof(fp)) {
104 off_t pos = ftello(fp);
105 if (pos >= 0) {
H. Peter Anvind81a2352016-09-21 14:03:18 -0700106 pos += bytes;
H. Peter Anvinbdae10b2016-03-08 01:22:13 -0800107 if (!fflush(fp) &&
H. Peter Anvind81a2352016-09-21 14:03:18 -0700108 !nasm_ftruncate(fileno(fp), pos) &&
109 !fseeko(fp, pos, SEEK_SET))
H. Peter Anvinbdae10b2016-03-08 01:22:13 -0800110 return;
111 }
112 }
113#endif
114
H. Peter Anvind81a2352016-09-21 14:03:18 -0700115 while (bytes > 0) {
H. Peter Anvinbdae10b2016-03-08 01:22:13 -0800116 blksize = (bytes < ZERO_BUF_SIZE) ? bytes : ZERO_BUF_SIZE;
117
118 nasm_write(zero_buffer, blksize, fp);
119 bytes -= blksize;
120 }
121}
H. Peter Anvin3e83cec2016-05-25 04:28:46 -0700122
H. Peter Anvin3e83cec2016-05-25 04:28:46 -0700123FILE *nasm_open_read(const char *filename, enum file_flags flags)
124{
125 FILE *f;
H. Peter Anvind81a2352016-09-21 14:03:18 -0700126 bool again = true;
H. Peter Anvin3e83cec2016-05-25 04:28:46 -0700127
H. Peter Anvind81a2352016-09-21 14:03:18 -0700128#ifdef __GLIBC__
129 /*
130 * Try to open this file with memory mapping for speed, unless we are
131 * going to do it "manually" with nasm_map_file()
132 */
133 if (!(flags & NF_FORMAP)) {
134 f = fopen(filename, (flags & NF_TEXT) ? "rtm" : "rbm");
135 again = (!f) && (errno == EINVAL); /* Not supported, try without m */
136 }
137#endif
138
139 if (again)
140 f = fopen(filename, (flags & NF_TEXT) ? "rt" : "rb");
141
H. Peter Anvin3e83cec2016-05-25 04:28:46 -0700142 if (!f && (flags & NF_FATAL))
143 nasm_fatal(ERR_NOFILE, "unable to open input file: `%s': %s",
144 filename, strerror(errno));
145
146 return f;
147}
148
149FILE *nasm_open_write(const char *filename, enum file_flags flags)
150{
151 FILE *f;
152
H. Peter Anvind81a2352016-09-21 14:03:18 -0700153 f = fopen(filename, (flags & NF_TEXT) ? "wt" : "wb");
154
H. Peter Anvin3e83cec2016-05-25 04:28:46 -0700155 if (!f && (flags & NF_FATAL))
156 nasm_fatal(ERR_NOFILE, "unable to open output file: `%s': %s",
157 filename, strerror(errno));
158
159 return f;
160}
H. Peter Anvinc1700892016-09-20 18:26:42 -0700161
H. Peter Anvind81a2352016-09-21 14:03:18 -0700162/*
163 * Report the existence of a file
164 */
165bool nasm_file_exists(const char *filename)
166{
167#if defined(HAVE_FACCESSAT) && defined(AT_EACCESS)
168 return faccessat(AT_FDCWD, filename, R_OK, AT_EACCESS) == 0;
169#elif defined(HAVE_ACCESS)
170 return access(filename, R_OK) == 0;
171#else
172 FILE *f;
173
174 f = fopen(filename, "rb");
175 if (f) {
176 fclose(f);
177 return true;
178 } else {
179 return false;
180 }
181#endif
182}
183
184/*
185 * Report file size. This MAY move the file pointer.
186 */
187off_t nasm_file_size(FILE *f)
188{
H. Peter Anvin397c1692016-10-04 17:01:59 -0700189#if defined(HAVE_FILENO) && defined(HAVE__FILELENGTHI64)
190 return _filelengthi64(fileno(f));
H. Peter Anvincbd72b62017-02-23 18:19:25 -0800191#elif defined(nasm_fstat)
192 struct nasm_stat st;
H. Peter Anvind81a2352016-09-21 14:03:18 -0700193
H. Peter Anvincbd72b62017-02-23 18:19:25 -0800194 if (nasm_fstat(fileno(f), &st))
H. Peter Anvind81a2352016-09-21 14:03:18 -0700195 return (off_t)-1;
196
197 return st.st_size;
198#else
199 if (fseeko(f, 0, SEEK_END))
200 return (off_t)-1;
201
202 return ftello(f);
203#endif
204}
205
206/*
207 * Report file size given pathname
208 */
209off_t nasm_file_size_by_path(const char *pathname)
210{
H. Peter Anvin675e7b72017-04-05 21:19:03 -0700211#ifdef nasm_stat
212 struct nasm_stat st;
H. Peter Anvind81a2352016-09-21 14:03:18 -0700213
H. Peter Anvin675e7b72017-04-05 21:19:03 -0700214 if (nasm_stat(pathname, &st))
H. Peter Anvind81a2352016-09-21 14:03:18 -0700215 return (off_t)-1;
216
217 return st.st_size;
218#else
219 FILE *fp;
220 off_t len;
221
222 fp = nasm_open_read(pathname, NF_BINARY);
223 if (!fp)
224 return (off_t)-1;
225
226 len = nasm_file_size(fp);
227 fclose(fp);
228
229 return len;
230#endif
231}