Coverage Report

Created: 2026-01-09 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/unit/src/nxt_file.c
Line
Count
Source
1
2
/*
3
 * Copyright (C) Igor Sysoev
4
 * Copyright (C) NGINX, Inc.
5
 */
6
7
#include <nxt_main.h>
8
9
10
nxt_int_t
11
nxt_file_open(nxt_task_t *task, nxt_file_t *file, nxt_uint_t mode,
12
    nxt_uint_t create, nxt_file_access_t access)
13
0
{
14
#ifdef __CYGWIN__
15
    mode |= O_BINARY;
16
#endif
17
18
    /* O_NONBLOCK is to prevent blocking on FIFOs, special devices, etc. */
19
0
    mode |= (O_NONBLOCK | create);
20
21
0
    file->fd = open((char *) file->name, mode, access);
22
23
0
    file->error = (file->fd == -1) ? nxt_errno : 0;
24
25
#if (NXT_DEBUG)
26
    nxt_thread_time_update(task->thread);
27
#endif
28
29
0
    nxt_debug(task, "open(\"%FN\", 0x%uXi, 0x%uXi): %FD err:%d",
30
0
              file->name, mode, access, file->fd, file->error);
31
32
0
    if (file->fd != -1) {
33
0
        return NXT_OK;
34
0
    }
35
36
0
    if (file->log_level != 0) {
37
0
        nxt_log(task, file->log_level, "open(\"%FN\") failed %E",
38
0
                file->name, file->error);
39
0
    }
40
41
0
    return NXT_ERROR;
42
0
}
43
44
45
#if (NXT_HAVE_OPENAT2)
46
47
nxt_int_t
48
nxt_file_openat2(nxt_task_t *task, nxt_file_t *file, nxt_uint_t mode,
49
    nxt_uint_t create, nxt_file_access_t access, nxt_fd_t dfd,
50
    nxt_uint_t resolve)
51
{
52
    struct open_how  how;
53
54
    nxt_memzero(&how, sizeof(how));
55
56
    /* O_NONBLOCK is to prevent blocking on FIFOs, special devices, etc. */
57
    mode |= (O_NONBLOCK | create);
58
59
    how.flags = mode;
60
    how.mode = access;
61
    how.resolve = resolve;
62
63
    file->fd = syscall(SYS_openat2, dfd, file->name, &how, sizeof(how));
64
65
    file->error = (file->fd == -1) ? nxt_errno : 0;
66
67
#if (NXT_DEBUG)
68
    nxt_thread_time_update(task->thread);
69
#endif
70
71
    nxt_debug(task, "openat2(%FD, \"%FN\"): %FD err:%d", dfd, file->name,
72
              file->fd, file->error);
73
74
    if (file->fd != -1) {
75
        return NXT_OK;
76
    }
77
78
    if (file->log_level != 0) {
79
        nxt_log(task, file->log_level, "openat2(%FD, \"%FN\") failed %E", dfd,
80
                file->name, file->error);
81
    }
82
83
    return NXT_ERROR;
84
}
85
86
#endif
87
88
89
void
90
nxt_file_close(nxt_task_t *task, nxt_file_t *file)
91
0
{
92
0
    nxt_debug(task, "close(%FD)", file->fd);
93
94
0
    if (close(file->fd) != 0) {
95
0
        nxt_alert(task, "close(%FD, \"%FN\") failed %E",
96
0
                  file->fd, file->name, nxt_errno);
97
0
    }
98
0
}
99
100
101
ssize_t
102
nxt_file_write(nxt_file_t *file, const u_char *buf, size_t size,
103
    nxt_off_t offset)
104
0
{
105
0
    ssize_t  n;
106
107
0
    nxt_thread_debug(thr);
108
109
0
    n = pwrite(file->fd, buf, size, offset);
110
111
0
    file->error = (n < 0) ? nxt_errno : 0;
112
113
0
    nxt_thread_time_debug_update(thr);
114
115
0
    nxt_log_debug(thr->log, "pwrite(%FD, %p, %uz, %O): %z",
116
0
                  file->fd, buf, size, offset, n);
117
118
0
    if (nxt_fast_path(n >= 0)) {
119
0
        return n;
120
0
    }
121
122
0
    nxt_thread_log_alert("pwrite(%FD, \"%FN\", %p, %uz, %O) failed %E",
123
0
                         file->fd, file->name, buf, size,
124
0
                         offset, file->error);
125
126
0
    return NXT_ERROR;
127
0
}
128
129
130
ssize_t
131
nxt_file_read(nxt_file_t *file, u_char *buf, size_t size, nxt_off_t offset)
132
0
{
133
0
    ssize_t  n;
134
135
0
    nxt_thread_debug(thr);
136
137
0
    n = pread(file->fd, buf, size, offset);
138
139
0
    file->error = (n <= 0) ? nxt_errno : 0;
140
141
0
    nxt_thread_time_debug_update(thr);
142
143
0
    nxt_log_debug(thr->log, "pread(%FD, %p, %uz, %O): %z",
144
0
                  file->fd, buf, size, offset, n);
145
146
0
    if (nxt_fast_path(n >= 0)) {
147
0
        return n;
148
0
    }
149
150
0
    nxt_thread_log_alert("pread(%FD, \"%FN\", %p, %uz, %O) failed %E",
151
0
                         file->fd, file->name, buf, size,
152
0
                         offset, file->error);
153
154
0
    return NXT_ERROR;
155
0
}
156
157
158
#if (NXT_HAVE_READAHEAD)
159
160
/* FreeBSD 8.0 fcntl(F_READAHEAD, size) enables read ahead up to the size. */
161
162
void
163
nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size)
164
{
165
    int     ret;
166
    u_char  buf;
167
168
    ret = fcntl(file->fd, F_READAHEAD, (int) size);
169
170
    nxt_thread_log_debug("fcntl(%FD, F_READAHEAD, %uz): %d",
171
                         file->fd, size, ret);
172
173
    if (nxt_fast_path(ret != -1)) {
174
        (void) nxt_file_read(file, &buf, 1, offset);
175
        return;
176
    }
177
178
    nxt_thread_log_alert("fcntl(%FD, \"%FN\", F_READAHEAD, %uz) failed %E",
179
                         file->fd, file->name, size, nxt_errno);
180
}
181
182
#elif (NXT_HAVE_POSIX_FADVISE)
183
184
/*
185
 * POSIX_FADV_SEQUENTIAL
186
 *   Linux doubles the default readahead window size of a backing device
187
 *   which is usually 128K.
188
 *
189
 *   FreeBSD does nothing.
190
 *
191
 * POSIX_FADV_WILLNEED
192
 *   Linux preloads synchronously up to 2M of specified file region in
193
 *   the kernel page cache.  Linux-specific readahead(2) syscall does
194
 *   the same.  Both operations are blocking despite posix_fadvise(2)
195
 *   claims the opposite.
196
 *
197
 *   FreeBSD does nothing.
198
 */
199
200
void
201
nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size)
202
0
{
203
0
    nxt_err_t  err;
204
205
0
    err = posix_fadvise(file->fd, offset, size, POSIX_FADV_WILLNEED);
206
207
0
    nxt_thread_log_debug("posix_fadvise(%FD, \"%FN\", %O, %uz, %d): %d",
208
0
                         file->fd, file->name, offset, size,
209
0
                         POSIX_FADV_WILLNEED, err);
210
211
0
    if (nxt_fast_path(err == 0)) {
212
0
        return;
213
0
    }
214
215
0
    nxt_thread_log_alert("posix_fadvise(%FD, \"%FN\", %O, %uz, %d) failed %E",
216
0
                         file->fd, file->name, offset, size,
217
0
                         POSIX_FADV_WILLNEED, err);
218
0
}
219
220
#elif (NXT_HAVE_RDAHEAD)
221
222
/* MacOSX fcntl(F_RDAHEAD). */
223
224
void
225
nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size)
226
{
227
    int     ret;
228
    u_char  buf;
229
230
    ret = fcntl(file->fd, F_RDAHEAD, 1);
231
232
    nxt_thread_log_debug("fcntl(%FD, F_RDAHEAD, 1): %d", file->fd, ret);
233
234
    if (nxt_fast_path(ret != -1)) {
235
        (void) nxt_file_read(file, &buf, 1, offset);
236
        return;
237
    }
238
239
    nxt_thread_log_alert("fcntl(%FD, \"%FN\", F_RDAHEAD, 1) failed %E",
240
                         file->fd, file->name, nxt_errno);
241
}
242
243
#else
244
245
void
246
nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size)
247
{
248
    u_char  buf;
249
250
    (void) nxt_file_read(file, &buf, 1, offset);
251
}
252
253
#endif
254
255
256
nxt_int_t
257
nxt_file_info(nxt_file_t *file, nxt_file_info_t *fi)
258
0
{
259
0
    int  n;
260
261
0
    if (file->fd == NXT_FILE_INVALID) {
262
0
        n = stat((char *) file->name, fi);
263
264
0
        file->error = (n != 0) ? nxt_errno : 0;
265
266
0
        nxt_thread_log_debug("stat(\"%FN)\": %d", file->name, n);
267
268
0
        if (n == 0) {
269
0
            return NXT_OK;
270
0
        }
271
272
0
        if (file->log_level != 0) {
273
0
            nxt_thread_log_error(file->log_level, "stat(\"%FN\") failed %E",
274
0
                                 file->name, file->error);
275
0
        }
276
277
0
        return NXT_ERROR;
278
279
0
    } else {
280
0
        n = fstat(file->fd, fi);
281
282
0
        file->error = (n != 0) ? nxt_errno : 0;
283
284
0
        nxt_thread_log_debug("fstat(%FD): %d", file->fd, n);
285
286
0
        if (n == 0) {
287
0
            return NXT_OK;
288
0
        }
289
290
        /* Use NXT_LOG_ALERT because fstat() error on open file is strange. */
291
292
0
        nxt_thread_log_alert("fstat(%FD, \"%FN\") failed %E",
293
0
                             file->fd, file->name, file->error);
294
295
0
        return NXT_ERROR;
296
0
    }
297
0
}
298
299
300
nxt_int_t
301
nxt_file_delete(nxt_file_name_t *name)
302
0
{
303
0
    nxt_thread_log_debug("unlink(\"%FN\")", name);
304
305
0
    if (nxt_fast_path(unlink((char *) name) == 0)) {
306
0
        return NXT_OK;
307
0
    }
308
309
0
    nxt_thread_log_alert("unlink(\"%FN\") failed %E", name, nxt_errno);
310
311
0
    return NXT_ERROR;
312
0
}
313
314
315
nxt_int_t
316
nxt_file_set_access(nxt_file_name_t *name, nxt_file_access_t access)
317
0
{
318
0
    if (nxt_fast_path(chmod((char *) name, access) == 0)) {
319
0
        return NXT_OK;
320
0
    }
321
322
0
    nxt_thread_log_alert("chmod(\"%FN\") failed %E", name, nxt_errno);
323
324
0
    return NXT_ERROR;
325
0
}
326
327
328
nxt_int_t
329
nxt_file_chown(nxt_file_name_t *name, const char *owner, const char *group)
330
0
{
331
0
    int    err;
332
0
    char   *buf;
333
0
    long   bufsize;
334
0
    gid_t  gid = ~0;
335
0
    uid_t  uid = ~0;
336
337
0
    if (owner == NULL && group == NULL) {
338
0
        return NXT_OK;
339
0
    }
340
341
0
    if (owner != NULL) {
342
0
        struct passwd  pwd, *result;
343
344
0
        bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
345
0
        if (bufsize == -1) {
346
0
            bufsize = 32768;
347
0
        }
348
349
0
        buf = nxt_malloc(bufsize);
350
0
        if (buf == NULL) {
351
0
            return NXT_ERROR;
352
0
        }
353
354
0
        err = getpwnam_r(owner, &pwd, buf, bufsize, &result);
355
0
        if (result == NULL) {
356
0
            nxt_thread_log_alert("getpwnam_r(\"%s\", ...) failed %E %s",
357
0
                                 owner, nxt_errno,
358
0
                                 err == 0 ? "(User not found)" : "");
359
0
            goto out_err_free;
360
0
        }
361
362
0
        uid = pwd.pw_uid;
363
364
0
        nxt_free(buf);
365
0
    }
366
367
0
    if (group != NULL) {
368
0
        struct group  grp, *result;
369
370
0
        bufsize = sysconf(_SC_GETGR_R_SIZE_MAX);
371
0
        if (bufsize == -1) {
372
0
            bufsize = 32768;
373
0
        }
374
375
0
        buf = nxt_malloc(bufsize);
376
0
        if (buf == NULL) {
377
0
            return NXT_ERROR;
378
0
        }
379
380
0
        err = getgrnam_r(group, &grp, buf, bufsize, &result);
381
0
        if (result == NULL) {
382
0
            nxt_thread_log_alert("getgrnam_r(\"%s\", ...) failed %E %s",
383
0
                                 group, nxt_errno,
384
0
                                 err == 0 ? "(Group not found)" : "");
385
0
            goto out_err_free;
386
0
        }
387
388
0
        gid = grp.gr_gid;
389
390
0
        nxt_free(buf);
391
0
    }
392
393
0
    if (nxt_fast_path(chown((const char *) name, uid, gid) == 0)) {
394
0
        return NXT_OK;
395
0
    }
396
397
0
    nxt_thread_log_alert("chown(\"%FN\", %l, %l) failed %E", name,
398
0
                         owner != NULL ? (long) uid : -1,
399
0
                         group != NULL ? (long) gid : -1, nxt_errno);
400
401
0
    return NXT_ERROR;
402
403
0
out_err_free:
404
0
    nxt_free(buf);
405
406
0
    return NXT_ERROR;
407
0
}
408
409
410
nxt_int_t
411
nxt_file_rename(nxt_file_name_t *old_name, nxt_file_name_t *new_name)
412
0
{
413
0
    int  ret;
414
415
0
    nxt_thread_log_debug("rename(\"%FN\", \"%FN\")", old_name, new_name);
416
417
0
    ret = rename((char *) old_name, (char *) new_name);
418
0
    if (nxt_fast_path(ret == 0)) {
419
0
        return NXT_OK;
420
0
    }
421
422
0
    nxt_thread_log_alert("rename(\"%FN\", \"%FN\") failed %E",
423
0
                         old_name, new_name, nxt_errno);
424
425
0
    return NXT_ERROR;
426
0
}
427
428
429
/*
430
 * ioctl(FIONBIO) sets a non-blocking mode using one syscall,
431
 * thereas fcntl(F_SETFL, O_NONBLOCK) needs to learn the current state
432
 * using fcntl(F_GETFL).
433
 *
434
 * ioctl() and fcntl() are syscalls at least in Linux 2.2, FreeBSD 2.x,
435
 * and Solaris 7.
436
 *
437
 * Linux 2.4 uses BKL for ioctl() and fcntl(F_SETFL).
438
 * Linux 2.6 does not use BKL.
439
 */
440
441
#if (NXT_HAVE_FIONBIO)
442
443
nxt_int_t
444
nxt_fd_nonblocking(nxt_task_t *task, nxt_fd_t fd)
445
0
{
446
0
    int  nb;
447
448
0
    nb = 1;
449
450
0
    if (nxt_fast_path(ioctl(fd, FIONBIO, &nb) != -1)) {
451
0
        return NXT_OK;
452
0
    }
453
454
0
    nxt_alert(task, "ioctl(%d, FIONBIO) failed %E", fd, nxt_errno);
455
456
0
    return NXT_ERROR;
457
458
0
}
459
460
461
nxt_int_t
462
nxt_fd_blocking(nxt_task_t *task, nxt_fd_t fd)
463
0
{
464
0
    int  nb;
465
466
0
    nb = 0;
467
468
0
    if (nxt_fast_path(ioctl(fd, FIONBIO, &nb) != -1)) {
469
0
        return NXT_OK;
470
0
    }
471
472
0
    nxt_alert(task, "ioctl(%d, !FIONBIO) failed %E", fd, nxt_errno);
473
474
0
    return NXT_ERROR;
475
0
}
476
477
#else /* !(NXT_HAVE_FIONBIO) */
478
479
nxt_int_t
480
nxt_fd_nonblocking(nxt_task_t *task, nxt_fd_t fd)
481
{
482
    int  flags;
483
484
    flags = fcntl(fd, F_GETFL);
485
486
    if (nxt_slow_path(flags == -1)) {
487
        nxt_alert(task, "fcntl(%d, F_GETFL) failed %E", fd, nxt_errno);
488
        return NXT_ERROR;
489
    }
490
491
    flags |= O_NONBLOCK;
492
493
    if (nxt_slow_path(fcntl(fd, F_SETFL, flags) == -1)) {
494
        nxt_alert(task, "fcntl(%d, F_SETFL, O_NONBLOCK) failed %E",
495
                  fd, nxt_errno);
496
        return NXT_ERROR;
497
    }
498
499
    return NXT_OK;
500
}
501
502
503
nxt_int_t
504
nxt_fd_blocking(nxt_task_t *task, nxt_fd_t fd)
505
{
506
    int  flags;
507
508
    flags = fcntl(fd, F_GETFL);
509
510
    if (nxt_slow_path(flags == -1)) {
511
        nxt_alert(task, "fcntl(%d, F_GETFL) failed %E", fd, nxt_errno);
512
        return NXT_ERROR;
513
    }
514
515
    flags &= O_NONBLOCK;
516
517
    if (nxt_slow_path(fcntl(fd, F_SETFL, flags) == -1)) {
518
        nxt_alert(task, "fcntl(%d, F_SETFL, !O_NONBLOCK) failed %E",
519
                  fd, nxt_errno);
520
        return NXT_ERROR;
521
    }
522
523
    return NXT_OK;
524
}
525
526
#endif /* NXT_HAVE_FIONBIO */
527
528
529
ssize_t
530
nxt_fd_write(nxt_fd_t fd, u_char *buf, size_t size)
531
0
{
532
0
    ssize_t    n;
533
0
    nxt_err_t  err;
534
535
0
    n = write(fd, buf, size);
536
537
0
    err = (n == -1) ? nxt_errno : 0;
538
539
0
    nxt_thread_log_debug("write(%FD, %p, %uz): %z", fd, buf, size, n);
540
541
0
    if (nxt_slow_path(n <= 0)) {
542
0
        nxt_thread_log_alert("write(%FD) failed %E", fd, err);
543
0
    }
544
545
0
    return n;
546
0
}
547
548
549
ssize_t
550
nxt_fd_read(nxt_fd_t fd, u_char *buf, size_t size)
551
0
{
552
0
    ssize_t    n;
553
0
    nxt_err_t  err;
554
555
0
    n = read(fd, buf, size);
556
557
0
    err = (n == -1) ? nxt_errno : 0;
558
559
0
    nxt_thread_log_debug("read(%FD, %p, %uz): %z", fd, buf, size, n);
560
561
0
    if (nxt_slow_path(n <= 0)) {
562
563
0
        if (err == NXT_EAGAIN) {
564
0
            return 0;
565
0
        }
566
567
0
        nxt_thread_log_alert("read(%FD) failed %E", fd, err);
568
0
    }
569
570
0
    return n;
571
0
}
572
573
574
void
575
nxt_fd_close(nxt_fd_t fd)
576
0
{
577
0
    nxt_thread_log_debug("close(%FD)", fd);
578
579
0
    if (nxt_slow_path(close(fd) != 0)) {
580
0
        nxt_thread_log_alert("close(%FD) failed %E", fd, nxt_errno);
581
0
    }
582
0
}
583
584
585
FILE *
586
nxt_file_fopen(nxt_task_t *task, const char *pathname, const char *mode)
587
0
{
588
0
    int   err;
589
0
    FILE  *fp;
590
591
#if (NXT_DEBUG)
592
    nxt_thread_time_update(task->thread);
593
#endif
594
595
0
    fp = fopen(pathname, mode);
596
0
    err = (fp == NULL) ? nxt_errno : 0;
597
598
0
    nxt_debug(task, "fopen(\"%s\", \"%s\"): fp:%p err:%d", pathname, mode, fp,
599
0
              err);
600
601
0
    if (nxt_fast_path(fp != NULL)) {
602
0
        return fp;
603
0
    }
604
605
0
    nxt_alert(task, "fopen(\"%s\") failed %E", pathname, err);
606
607
0
    return NULL;
608
0
}
609
610
611
void
612
nxt_file_fclose(nxt_task_t *task, FILE *fp)
613
0
{
614
0
    nxt_debug(task, "fclose(%p)", fp);
615
616
0
    if (nxt_slow_path(fclose(fp) == -1)) {
617
0
        nxt_alert(task, "fclose() failed %E", nxt_errno);
618
0
    }
619
0
}
620
621
622
/*
623
 * nxt_file_redirect() redirects the file to the fd descriptor.
624
 * Then the fd descriptor is closed.
625
 */
626
627
nxt_int_t
628
nxt_file_redirect(nxt_file_t *file, nxt_fd_t fd)
629
0
{
630
0
    nxt_thread_log_debug("dup2(%FD, %FD, \"%FN\")", fd, file->fd, file->name);
631
632
0
    if (dup2(fd, file->fd) == -1) {
633
0
        nxt_thread_log_alert("dup2(%FD, %FD, \"%FN\") failed %E",
634
0
                             fd, file->fd, file->name, nxt_errno);
635
0
        return NXT_ERROR;
636
0
    }
637
638
0
    if (close(fd) != 0) {
639
0
        nxt_thread_log_alert("close(%FD, \"%FN\") failed %E",
640
0
                             fd, file->name, nxt_errno);
641
0
        return NXT_ERROR;
642
0
    }
643
644
0
    return NXT_OK;
645
0
}
646
647
648
/* nxt_file_stdout() redirects the stdout descriptor to the file. */
649
650
nxt_int_t
651
nxt_file_stdout(nxt_file_t *file)
652
0
{
653
0
    nxt_thread_log_debug("dup2(%FD, %FD, \"%FN\")",
654
0
                         file->fd, STDOUT_FILENO, file->name);
655
656
0
    if (dup2(file->fd, STDOUT_FILENO) != -1) {
657
0
        return NXT_OK;
658
0
    }
659
660
0
    nxt_thread_log_alert("dup2(%FD, %FD, \"%FN\") failed %E",
661
0
                         file->fd, STDOUT_FILENO, file->name, nxt_errno);
662
663
0
    return NXT_ERROR;
664
0
}
665
666
667
/* nxt_file_stderr() redirects the stderr descriptor to the file. */
668
669
nxt_int_t
670
nxt_file_stderr(nxt_file_t *file)
671
0
{
672
0
    nxt_thread_log_debug("dup2(%FD, %FD, \"%FN\")",
673
0
                         file->fd, STDERR_FILENO, file->name);
674
675
0
    if (dup2(file->fd, STDERR_FILENO) != -1) {
676
0
        return NXT_OK;
677
0
    }
678
679
0
    nxt_thread_log_alert("dup2(%FD, %FD, \"%FN\") failed %E",
680
0
                         file->fd, STDERR_FILENO, file->name, nxt_errno);
681
682
0
    return NXT_ERROR;
683
0
}
684
685
686
nxt_int_t
687
nxt_stderr_start(void)
688
2
{
689
2
    int  flags, fd;
690
691
2
    flags = fcntl(nxt_stderr, F_GETFL);
692
693
2
    if (flags != -1) {
694
        /*
695
         * If the stderr output of a multithreaded application is
696
         * redirected to a file:
697
         *    Linux, Solaris and MacOSX do not write atomically to the output;
698
         *    MacOSX besides adds zeroes to the output.
699
         * O_APPEND fixes this.
700
         */
701
2
        (void) fcntl(nxt_stderr, F_SETFL, flags | O_APPEND);
702
703
2
    } else {
704
        /*
705
         * The stderr descriptor is closed before application start.
706
         * Reserve the stderr descriptor for future use.  Errors are
707
         * ignored because anyway they could be written nowhere.
708
         */
709
0
        fd = open("/dev/null", O_WRONLY | O_APPEND);
710
711
0
        if (fd != -1) {
712
0
            (void) dup2(fd, nxt_stderr);
713
714
0
            if (fd != nxt_stderr) {
715
0
                (void) close(fd);
716
0
            }
717
0
        }
718
0
    }
719
720
2
    return flags;
721
2
}
722
723
724
nxt_int_t
725
nxt_pipe_create(nxt_task_t *task, nxt_fd_t *pp, nxt_bool_t nbread,
726
    nxt_bool_t nbwrite)
727
0
{
728
0
    if (pipe(pp) != 0) {
729
0
        nxt_alert(task, "pipe() failed %E", nxt_errno);
730
731
0
        return NXT_ERROR;
732
0
    }
733
734
0
    nxt_debug(task, "pipe(): %FD:%FD", pp[0], pp[1]);
735
736
0
    if (nbread) {
737
0
        if (nxt_fd_nonblocking(task, pp[0]) != NXT_OK) {
738
0
            return NXT_ERROR;
739
0
        }
740
0
    }
741
742
0
    if (nbwrite) {
743
0
        if (nxt_fd_nonblocking(task, pp[1]) != NXT_OK) {
744
0
            return NXT_ERROR;
745
0
        }
746
0
    }
747
748
0
    return NXT_OK;
749
0
}
750
751
752
void
753
nxt_pipe_close(nxt_task_t *task, nxt_fd_t *pp)
754
0
{
755
0
    nxt_debug(task, "pipe close(%FD:%FD)", pp[0], pp[1]);
756
757
0
    if (close(pp[0]) != 0) {
758
0
        nxt_alert(task, "pipe close(%FD) failed %E", pp[0], nxt_errno);
759
0
    }
760
761
0
    if (close(pp[1]) != 0) {
762
0
        nxt_alert(task, "pipe close(%FD) failed %E", pp[1], nxt_errno);
763
0
    }
764
0
}
765
766
767
size_t
768
nxt_dir_current(char *buf, size_t len)
769
0
{
770
0
    if (nxt_fast_path(getcwd(buf, len) != NULL)) {
771
0
        return nxt_strlen(buf);
772
0
    }
773
774
0
    nxt_thread_log_alert("getcwd(%uz) failed %E", len, nxt_errno);
775
776
0
    return 0;
777
0
}