1 | /* ----------------------------------------------------------------------- * |
2 | * |
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. |
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 | |
34 | #include "file.h" |
35 | |
36 | void 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 | |
46 | void 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 | void fwriteint16_t(uint16_t data, FILE * fp) |
54 | { |
55 | data = cpu_to_le16(data); |
56 | nasm_write(&data, 2, fp); |
57 | } |
58 | |
59 | void fwriteint32_t(uint32_t data, FILE * fp) |
60 | { |
61 | data = cpu_to_le32(data); |
62 | nasm_write(&data, 4, fp); |
63 | } |
64 | |
65 | void fwriteint64_t(uint64_t data, FILE * fp) |
66 | { |
67 | data = cpu_to_le64(data); |
68 | nasm_write(&data, 8, fp); |
69 | } |
70 | |
71 | void fwriteaddr(uint64_t data, int size, FILE * fp) |
72 | { |
73 | data = cpu_to_le64(data); |
74 | nasm_write(&data, size, fp); |
75 | } |
76 | |
77 | void fwritezero(off_t bytes, FILE *fp) |
78 | { |
79 | size_t blksize; |
80 | |
81 | #ifdef nasm_ftruncate |
82 | if (bytes >= BUFSIZ && !ferror(fp) && !feof(fp)) { |
83 | off_t pos = ftello(fp); |
84 | if (pos >= 0) { |
85 | pos += bytes; |
86 | if (!fflush(fp) && |
87 | !nasm_ftruncate(fileno(fp), pos) && |
88 | !fseeko(fp, pos, SEEK_SET)) |
89 | return; |
90 | } |
91 | } |
92 | #endif |
93 | |
94 | while (bytes > 0) { |
95 | blksize = (bytes < ZERO_BUF_SIZE) ? bytes : ZERO_BUF_SIZE; |
96 | |
97 | nasm_write(zero_buffer, blksize, fp); |
98 | bytes -= blksize; |
99 | } |
100 | } |
101 | |
102 | FILE *nasm_open_read(const char *filename, enum file_flags flags) |
103 | { |
104 | FILE *f = NULL; |
105 | bool again = true; |
106 | |
107 | #ifdef __GLIBC__ |
108 | /* |
109 | * Try to open this file with memory mapping for speed, unless we are |
110 | * going to do it "manually" with nasm_map_file() |
111 | */ |
112 | if (!(flags & NF_FORMAP)) { |
113 | f = fopen(filename, (flags & NF_TEXT) ? "rtm" : "rbm" ); |
114 | again = (!f) && (errno == EINVAL); /* Not supported, try without m */ |
115 | } |
116 | #endif |
117 | |
118 | if (again) |
119 | f = fopen(filename, (flags & NF_TEXT) ? "rt" : "rb" ); |
120 | |
121 | if (!f && (flags & NF_FATAL)) |
122 | nasm_fatal(ERR_NOFILE, "unable to open input file: `%s': %s" , |
123 | filename, strerror(errno)); |
124 | |
125 | return f; |
126 | } |
127 | |
128 | FILE *nasm_open_write(const char *filename, enum file_flags flags) |
129 | { |
130 | FILE *f; |
131 | |
132 | f = fopen(filename, (flags & NF_TEXT) ? "wt" : "wb" ); |
133 | |
134 | if (!f && (flags & NF_FATAL)) |
135 | nasm_fatal(ERR_NOFILE, "unable to open output file: `%s': %s" , |
136 | filename, strerror(errno)); |
137 | |
138 | return f; |
139 | } |
140 | |
141 | /* |
142 | * Report the existence of a file |
143 | */ |
144 | bool nasm_file_exists(const char *filename) |
145 | { |
146 | #if defined(HAVE_FACCESSAT) && defined(AT_EACCESS) |
147 | return faccessat(AT_FDCWD, filename, R_OK, AT_EACCESS) == 0; |
148 | #elif defined(HAVE_ACCESS) |
149 | return access(filename, R_OK) == 0; |
150 | #else |
151 | FILE *f; |
152 | |
153 | f = fopen(filename, "rb" ); |
154 | if (f) { |
155 | fclose(f); |
156 | return true; |
157 | } else { |
158 | return false; |
159 | } |
160 | #endif |
161 | } |
162 | |
163 | /* |
164 | * Report file size. This MAY move the file pointer. |
165 | */ |
166 | off_t nasm_file_size(FILE *f) |
167 | { |
168 | #ifdef HAVE__FILELENGTHI64 |
169 | return _filelengthi64(fileno(f)); |
170 | #elif defined(nasm_fstat) |
171 | nasm_struct_stat st; |
172 | |
173 | if (nasm_fstat(fileno(f), &st)) |
174 | return (off_t)-1; |
175 | |
176 | return st.st_size; |
177 | #else |
178 | if (fseeko(f, 0, SEEK_END)) |
179 | return (off_t)-1; |
180 | |
181 | return ftello(f); |
182 | #endif |
183 | } |
184 | |
185 | /* |
186 | * Report file size given pathname |
187 | */ |
188 | off_t nasm_file_size_by_path(const char *pathname) |
189 | { |
190 | #ifdef nasm_stat |
191 | nasm_struct_stat st; |
192 | |
193 | if (nasm_stat(pathname, &st)) |
194 | return (off_t)-1; |
195 | |
196 | return st.st_size; |
197 | #else |
198 | FILE *fp; |
199 | off_t len; |
200 | |
201 | fp = nasm_open_read(pathname, NF_BINARY); |
202 | if (!fp) |
203 | return (off_t)-1; |
204 | |
205 | len = nasm_file_size(fp); |
206 | fclose(fp); |
207 | |
208 | return len; |
209 | #endif |
210 | } |
211 | |
212 | /* |
213 | * Report the timestamp on a file, returns true if successful |
214 | */ |
215 | bool nasm_file_time(time_t *t, const char *pathname) |
216 | { |
217 | #ifdef nasm_stat |
218 | nasm_struct_stat st; |
219 | |
220 | if (nasm_stat(pathname, &st)) |
221 | return false; |
222 | |
223 | *t = st.st_mtime; |
224 | return true; |
225 | #else |
226 | return false; /* No idea how to do this on this OS */ |
227 | #endif |
228 | } |
229 | |