0
|
1
|
|
2 /*
|
|
3 * Copyright (C) Igor Sysoev
|
|
4 */
|
|
5
|
|
6
|
|
7 #include <ngx_config.h>
|
|
8 #include <ngx_core.h>
|
|
9
|
|
10
|
110
|
11 ssize_t
|
|
12 ngx_read_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
|
0
|
13 {
|
110
|
14 ssize_t n;
|
0
|
15
|
|
16 ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
|
10
|
17 "read: %d, %p, %uz, %O", file->fd, buf, size, offset);
|
0
|
18
|
18
|
19 #if (NGX_HAVE_PREAD)
|
0
|
20
|
|
21 n = pread(file->fd, buf, size, offset);
|
|
22
|
|
23 if (n == -1) {
|
|
24 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
|
|
25 "pread() failed, file \"%s\"", file->name.data);
|
|
26 return NGX_ERROR;
|
|
27 }
|
|
28
|
|
29 #else
|
|
30
|
|
31 if (file->sys_offset != offset) {
|
|
32 if (lseek(file->fd, offset, SEEK_SET) == -1) {
|
|
33 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed");
|
|
34 return NGX_ERROR;
|
|
35 }
|
|
36
|
|
37 file->sys_offset = offset;
|
|
38 }
|
|
39
|
|
40 n = read(file->fd, buf, size);
|
|
41
|
|
42 if (n == -1) {
|
|
43 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "read() failed");
|
|
44 return NGX_ERROR;
|
|
45 }
|
|
46
|
|
47 file->sys_offset += n;
|
|
48
|
|
49 #endif
|
|
50
|
|
51 file->offset += n;
|
|
52
|
|
53 return n;
|
|
54 }
|
|
55
|
|
56
|
110
|
57 ssize_t
|
|
58 ngx_write_file(ngx_file_t *file, u_char *buf, size_t size, off_t offset)
|
0
|
59 {
|
110
|
60 ssize_t n;
|
0
|
61
|
10
|
62 ngx_log_debug4(NGX_LOG_DEBUG_CORE, file->log, 0,
|
|
63 "write: %d, %p, %uz, %O", file->fd, buf, size, offset);
|
|
64
|
18
|
65 #if (NGX_HAVE_PWRITE)
|
0
|
66
|
|
67 n = pwrite(file->fd, buf, size, offset);
|
|
68
|
|
69 if (n == -1) {
|
|
70 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "pwrite() failed");
|
|
71 return NGX_ERROR;
|
|
72 }
|
|
73
|
|
74 if ((size_t) n != size) {
|
|
75 ngx_log_error(NGX_LOG_CRIT, file->log, 0,
|
10
|
76 "pwrite() has written only %z of %uz", n, size);
|
0
|
77 return NGX_ERROR;
|
|
78 }
|
|
79
|
|
80 #else
|
|
81
|
|
82 if (file->sys_offset != offset) {
|
|
83 if (lseek(file->fd, offset, SEEK_SET) == -1) {
|
|
84 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "lseek() failed");
|
|
85 return NGX_ERROR;
|
|
86 }
|
|
87
|
|
88 file->sys_offset = offset;
|
|
89 }
|
|
90
|
|
91 n = write(file->fd, buf, size);
|
|
92
|
|
93 if (n == -1) {
|
|
94 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno, "write() failed");
|
|
95 return NGX_ERROR;
|
|
96 }
|
|
97
|
|
98 if ((size_t) n != size) {
|
|
99 ngx_log_error(NGX_LOG_CRIT, file->log, 0,
|
10
|
100 "write() has written only %z of %uz", n, size);
|
0
|
101 return NGX_ERROR;
|
|
102 }
|
|
103
|
|
104 file->sys_offset += n;
|
|
105
|
|
106 #endif
|
|
107
|
|
108 file->offset += n;
|
|
109
|
|
110 return n;
|
|
111 }
|
|
112
|
|
113
|
110
|
114 ngx_fd_t
|
182
|
115 ngx_open_tempfile(u_char *name, ngx_uint_t persistent, ngx_uint_t mode)
|
0
|
116 {
|
|
117 ngx_fd_t fd;
|
|
118
|
182
|
119 fd = open((const char *) name, O_CREAT|O_EXCL|O_RDWR, mode ? mode : 0600);
|
0
|
120
|
|
121 if (fd != -1 && !persistent) {
|
|
122 unlink((const char *) name);
|
|
123 }
|
|
124
|
|
125 return fd;
|
|
126 }
|
|
127
|
|
128
|
10
|
129 #define NGX_IOVS 8
|
|
130
|
110
|
131 ssize_t
|
|
132 ngx_write_chain_to_file(ngx_file_t *file, ngx_chain_t *cl, off_t offset,
|
|
133 ngx_pool_t *pool)
|
0
|
134 {
|
|
135 u_char *prev;
|
|
136 size_t size;
|
|
137 ssize_t n;
|
10
|
138 ngx_array_t vec;
|
|
139 struct iovec *iov, iovs[NGX_IOVS];
|
0
|
140
|
10
|
141 /* use pwrite() if there is the only buf in a chain */
|
0
|
142
|
|
143 if (cl->next == NULL) {
|
|
144 return ngx_write_file(file, cl->buf->pos,
|
|
145 (size_t) (cl->buf->last - cl->buf->pos),
|
|
146 offset);
|
|
147 }
|
|
148
|
10
|
149 vec.elts = iovs;
|
|
150 vec.size = sizeof(struct iovec);
|
126
|
151 vec.nalloc = NGX_IOVS;
|
10
|
152 vec.pool = pool;
|
0
|
153
|
10
|
154 do {
|
|
155 prev = NULL;
|
|
156 iov = NULL;
|
|
157 size = 0;
|
0
|
158
|
10
|
159 vec.nelts = 0;
|
|
160
|
|
161 /* create the iovec and coalesce the neighbouring bufs */
|
0
|
162
|
10
|
163 while (cl && vec.nelts < IOV_MAX) {
|
|
164 if (prev == cl->buf->pos) {
|
|
165 iov->iov_len += cl->buf->last - cl->buf->pos;
|
0
|
166
|
10
|
167 } else {
|
50
|
168 iov = ngx_array_push(&vec);
|
|
169 if (iov == NULL) {
|
10
|
170 return NGX_ERROR;
|
|
171 }
|
|
172
|
|
173 iov->iov_base = (void *) cl->buf->pos;
|
|
174 iov->iov_len = cl->buf->last - cl->buf->pos;
|
|
175 }
|
|
176
|
|
177 size += cl->buf->last - cl->buf->pos;
|
|
178 prev = cl->buf->last;
|
|
179 cl = cl->next;
|
0
|
180 }
|
|
181
|
10
|
182 /* use pwrite() if there is the only iovec buffer */
|
0
|
183
|
10
|
184 if (vec.nelts == 1) {
|
|
185 iov = vec.elts;
|
|
186 return ngx_write_file(file, (u_char *) iov[0].iov_base,
|
|
187 iov[0].iov_len, offset);
|
|
188 }
|
0
|
189
|
10
|
190 if (file->sys_offset != offset) {
|
|
191 if (lseek(file->fd, offset, SEEK_SET) == -1) {
|
|
192 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
|
|
193 "lseek() failed");
|
|
194 return NGX_ERROR;
|
|
195 }
|
0
|
196
|
10
|
197 file->sys_offset = offset;
|
|
198 }
|
|
199
|
|
200 n = writev(file->fd, vec.elts, vec.nelts);
|
|
201
|
|
202 if (n == -1) {
|
|
203 ngx_log_error(NGX_LOG_CRIT, file->log, ngx_errno,
|
|
204 "writev() failed");
|
0
|
205 return NGX_ERROR;
|
|
206 }
|
|
207
|
10
|
208 if ((size_t) n != size) {
|
|
209 ngx_log_error(NGX_LOG_CRIT, file->log, 0,
|
|
210 "writev() has written only %z of %uz", n, size);
|
|
211 return NGX_ERROR;
|
|
212 }
|
0
|
213
|
10
|
214 file->sys_offset += n;
|
|
215 file->offset += n;
|
0
|
216
|
10
|
217 } while (cl);
|
0
|
218
|
|
219 return n;
|
|
220 }
|
|
221
|
|
222
|
110
|
223 ngx_int_t
|
230
|
224 ngx_set_file_time(u_char *name, ngx_fd_t fd, time_t s)
|
|
225 {
|
|
226 struct timeval tv[2];
|
|
227
|
|
228 tv[0].tv_sec = s;
|
|
229 tv[0].tv_usec = 0;
|
|
230 tv[1].tv_sec = s;
|
|
231 tv[1].tv_usec = 0;
|
|
232
|
|
233 if (utimes((char *) name, tv) != -1) {
|
|
234 return NGX_OK;
|
|
235 }
|
|
236
|
|
237 return NGX_ERROR;
|
|
238 }
|
|
239
|
|
240
|
|
241 ngx_int_t
|
110
|
242 ngx_open_dir(ngx_str_t *name, ngx_dir_t *dir)
|
0
|
243 {
|
|
244 dir->dir = opendir((const char *) name->data);
|
|
245
|
|
246 if (dir->dir == NULL) {
|
|
247 return NGX_ERROR;
|
|
248 }
|
|
249
|
6
|
250 dir->valid_info = 0;
|
0
|
251
|
|
252 return NGX_OK;
|
|
253 }
|
110
|
254
|
|
255
|
160
|
256 ngx_err_t
|
|
257 ngx_trylock_fd(ngx_fd_t fd)
|
110
|
258 {
|
|
259 struct flock fl;
|
|
260
|
160
|
261 fl.l_start = 0;
|
|
262 fl.l_len = 0;
|
|
263 fl.l_pid = 0;
|
|
264 fl.l_type = F_WRLCK;
|
110
|
265 fl.l_whence = SEEK_SET;
|
160
|
266
|
|
267 if (fcntl(fd, F_SETLK, &fl) == -1) {
|
|
268 return ngx_errno;
|
|
269 }
|
|
270
|
|
271 return 0;
|
|
272 }
|
|
273
|
|
274
|
|
275 ngx_err_t
|
|
276 ngx_lock_fd(ngx_fd_t fd)
|
|
277 {
|
|
278 struct flock fl;
|
|
279
|
|
280 fl.l_start = 0;
|
110
|
281 fl.l_len = 0;
|
|
282 fl.l_pid = 0;
|
|
283 fl.l_type = F_WRLCK;
|
160
|
284 fl.l_whence = SEEK_SET;
|
110
|
285
|
160
|
286 if (fcntl(fd, F_SETLKW, &fl) == -1) {
|
|
287 return ngx_errno;
|
110
|
288 }
|
|
289
|
160
|
290 return 0;
|
110
|
291 }
|
|
292
|
|
293
|
160
|
294 ngx_err_t
|
|
295 ngx_unlock_fd(ngx_fd_t fd)
|
110
|
296 {
|
|
297 struct flock fl;
|
|
298
|
160
|
299 fl.l_start = 0;
|
110
|
300 fl.l_len = 0;
|
|
301 fl.l_pid = 0;
|
|
302 fl.l_type = F_UNLCK;
|
160
|
303 fl.l_whence = SEEK_SET;
|
110
|
304
|
160
|
305 if (fcntl(fd, F_SETLK, &fl) == -1) {
|
|
306 return ngx_errno;
|
110
|
307 }
|
|
308
|
160
|
309 return 0;
|
110
|
310 }
|