10Sigor@sysoev.ru 20Sigor@sysoev.ru /* 30Sigor@sysoev.ru * Copyright (C) Igor Sysoev 40Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 50Sigor@sysoev.ru */ 60Sigor@sysoev.ru 70Sigor@sysoev.ru #include <nxt_main.h> 80Sigor@sysoev.ru 90Sigor@sysoev.ru 100Sigor@sysoev.ru nxt_int_t 1120Sigor@sysoev.ru nxt_file_open(nxt_task_t *task, nxt_file_t *file, nxt_uint_t mode, 1220Sigor@sysoev.ru nxt_uint_t create, nxt_file_access_t access) 130Sigor@sysoev.ru { 140Sigor@sysoev.ru #ifdef __CYGWIN__ 150Sigor@sysoev.ru mode |= O_BINARY; 160Sigor@sysoev.ru #endif 170Sigor@sysoev.ru 180Sigor@sysoev.ru /* O_NONBLOCK is to prevent blocking on FIFOs, special devices, etc. */ 190Sigor@sysoev.ru mode |= (O_NONBLOCK | create); 200Sigor@sysoev.ru 210Sigor@sysoev.ru file->fd = open((char *) file->name, mode, access); 220Sigor@sysoev.ru 230Sigor@sysoev.ru file->error = (file->fd == -1) ? nxt_errno : 0; 240Sigor@sysoev.ru 2520Sigor@sysoev.ru #if (NXT_DEBUG) 2620Sigor@sysoev.ru nxt_thread_time_update(task->thread); 2720Sigor@sysoev.ru #endif 280Sigor@sysoev.ru 2920Sigor@sysoev.ru nxt_debug(task, "open(\"%FN\", 0x%uXi, 0x%uXi): %FD err:%d", 3020Sigor@sysoev.ru file->name, mode, access, file->fd, file->error); 310Sigor@sysoev.ru 320Sigor@sysoev.ru if (file->fd != -1) { 330Sigor@sysoev.ru return NXT_OK; 340Sigor@sysoev.ru } 350Sigor@sysoev.ru 360Sigor@sysoev.ru if (file->log_level != 0) { 3720Sigor@sysoev.ru nxt_log(task, file->log_level, "open(\"%FN\") failed %E", 3820Sigor@sysoev.ru file->name, file->error); 390Sigor@sysoev.ru } 400Sigor@sysoev.ru 410Sigor@sysoev.ru return NXT_ERROR; 420Sigor@sysoev.ru } 430Sigor@sysoev.ru 440Sigor@sysoev.ru 450Sigor@sysoev.ru void 4620Sigor@sysoev.ru nxt_file_close(nxt_task_t *task, nxt_file_t *file) 470Sigor@sysoev.ru { 4820Sigor@sysoev.ru nxt_debug(task, "close(%FD)", file->fd); 490Sigor@sysoev.ru 500Sigor@sysoev.ru if (close(file->fd) != 0) { 51*564Svbart@nginx.com nxt_alert(task, "close(%FD, \"%FN\") failed %E", 52*564Svbart@nginx.com file->fd, file->name, nxt_errno); 530Sigor@sysoev.ru } 540Sigor@sysoev.ru } 550Sigor@sysoev.ru 560Sigor@sysoev.ru 570Sigor@sysoev.ru ssize_t 580Sigor@sysoev.ru nxt_file_write(nxt_file_t *file, const u_char *buf, size_t size, 590Sigor@sysoev.ru nxt_off_t offset) 600Sigor@sysoev.ru { 610Sigor@sysoev.ru ssize_t n; 620Sigor@sysoev.ru 630Sigor@sysoev.ru nxt_thread_debug(thr); 640Sigor@sysoev.ru 650Sigor@sysoev.ru n = pwrite(file->fd, buf, size, offset); 660Sigor@sysoev.ru 670Sigor@sysoev.ru file->error = (n < 0) ? nxt_errno : 0; 680Sigor@sysoev.ru 690Sigor@sysoev.ru nxt_thread_time_debug_update(thr); 700Sigor@sysoev.ru 710Sigor@sysoev.ru nxt_log_debug(thr->log, "pwrite(%FD, %p, %uz, %O): %z", 720Sigor@sysoev.ru file->fd, buf, size, offset, n); 730Sigor@sysoev.ru 740Sigor@sysoev.ru if (nxt_fast_path(n >= 0)) { 750Sigor@sysoev.ru return n; 760Sigor@sysoev.ru } 770Sigor@sysoev.ru 78*564Svbart@nginx.com nxt_thread_log_alert("pwrite(%FD, \"%FN\", %p, %uz, %O) failed %E", 790Sigor@sysoev.ru file->fd, file->name, buf, size, 800Sigor@sysoev.ru offset, file->error); 810Sigor@sysoev.ru 820Sigor@sysoev.ru return NXT_ERROR; 830Sigor@sysoev.ru } 840Sigor@sysoev.ru 850Sigor@sysoev.ru 860Sigor@sysoev.ru ssize_t 870Sigor@sysoev.ru nxt_file_read(nxt_file_t *file, u_char *buf, size_t size, nxt_off_t offset) 880Sigor@sysoev.ru { 890Sigor@sysoev.ru ssize_t n; 900Sigor@sysoev.ru 910Sigor@sysoev.ru nxt_thread_debug(thr); 920Sigor@sysoev.ru 930Sigor@sysoev.ru n = pread(file->fd, buf, size, offset); 940Sigor@sysoev.ru 950Sigor@sysoev.ru file->error = (n <= 0) ? nxt_errno : 0; 960Sigor@sysoev.ru 970Sigor@sysoev.ru nxt_thread_time_debug_update(thr); 980Sigor@sysoev.ru 990Sigor@sysoev.ru nxt_log_debug(thr->log, "pread(%FD, %p, %uz, %O): %z", 1000Sigor@sysoev.ru file->fd, buf, size, offset, n); 1010Sigor@sysoev.ru 1020Sigor@sysoev.ru if (nxt_fast_path(n >= 0)) { 1030Sigor@sysoev.ru return n; 1040Sigor@sysoev.ru } 1050Sigor@sysoev.ru 106*564Svbart@nginx.com nxt_thread_log_alert("pread(%FD, \"%FN\", %p, %uz, %O) failed %E", 1070Sigor@sysoev.ru file->fd, file->name, buf, size, 1080Sigor@sysoev.ru offset, file->error); 1090Sigor@sysoev.ru 1100Sigor@sysoev.ru return NXT_ERROR; 1110Sigor@sysoev.ru } 1120Sigor@sysoev.ru 1130Sigor@sysoev.ru 1140Sigor@sysoev.ru #if (NXT_HAVE_READAHEAD) 1150Sigor@sysoev.ru 1160Sigor@sysoev.ru /* FreeBSD 8.0 fcntl(F_READAHEAD, size) enables read ahead up to the size. */ 1170Sigor@sysoev.ru 1180Sigor@sysoev.ru void 1190Sigor@sysoev.ru nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) 1200Sigor@sysoev.ru { 1210Sigor@sysoev.ru int ret; 1220Sigor@sysoev.ru u_char buf; 1230Sigor@sysoev.ru 1240Sigor@sysoev.ru ret = fcntl(file->fd, F_READAHEAD, (int) size); 1250Sigor@sysoev.ru 1260Sigor@sysoev.ru nxt_thread_log_debug("fcntl(%FD, F_READAHEAD, %uz): %d", 1270Sigor@sysoev.ru file->fd, size, ret); 1280Sigor@sysoev.ru 1290Sigor@sysoev.ru if (nxt_fast_path(ret != -1)) { 1300Sigor@sysoev.ru (void) nxt_file_read(file, &buf, 1, offset); 1310Sigor@sysoev.ru return; 1320Sigor@sysoev.ru } 1330Sigor@sysoev.ru 134*564Svbart@nginx.com nxt_thread_log_alert("fcntl(%FD, \"%FN\", F_READAHEAD, %uz) failed %E", 1350Sigor@sysoev.ru file->fd, file->name, size, nxt_errno); 1360Sigor@sysoev.ru } 1370Sigor@sysoev.ru 1380Sigor@sysoev.ru #elif (NXT_HAVE_POSIX_FADVISE) 1390Sigor@sysoev.ru 1400Sigor@sysoev.ru /* 1410Sigor@sysoev.ru * POSIX_FADV_SEQUENTIAL 1420Sigor@sysoev.ru * Linux doubles the default readahead window size of a backing device 1430Sigor@sysoev.ru * which is usually 128K. 1440Sigor@sysoev.ru * 1450Sigor@sysoev.ru * FreeBSD does nothing. 1460Sigor@sysoev.ru * 1470Sigor@sysoev.ru * POSIX_FADV_WILLNEED 1480Sigor@sysoev.ru * Linux preloads synchronously up to 2M of specified file region in 1490Sigor@sysoev.ru * the kernel page cache. Linux-specific readahead(2) syscall does 1500Sigor@sysoev.ru * the same. Both operations are blocking despite posix_fadvise(2) 1510Sigor@sysoev.ru * claims the opposite. 1520Sigor@sysoev.ru * 1530Sigor@sysoev.ru * FreeBSD does nothing. 1540Sigor@sysoev.ru */ 1550Sigor@sysoev.ru 1560Sigor@sysoev.ru void 1570Sigor@sysoev.ru nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) 1580Sigor@sysoev.ru { 1590Sigor@sysoev.ru nxt_err_t err; 1600Sigor@sysoev.ru 1610Sigor@sysoev.ru err = posix_fadvise(file->fd, offset, size, POSIX_FADV_WILLNEED); 1620Sigor@sysoev.ru 1630Sigor@sysoev.ru nxt_thread_log_debug("posix_fadvise(%FD, \"%FN\", %O, %uz, %d): %d", 1640Sigor@sysoev.ru file->fd, file->name, offset, size, 1650Sigor@sysoev.ru POSIX_FADV_WILLNEED, err); 1660Sigor@sysoev.ru 1670Sigor@sysoev.ru if (nxt_fast_path(err == 0)) { 1680Sigor@sysoev.ru return; 1690Sigor@sysoev.ru } 1700Sigor@sysoev.ru 171*564Svbart@nginx.com nxt_thread_log_alert("posix_fadvise(%FD, \"%FN\", %O, %uz, %d) failed %E", 1720Sigor@sysoev.ru file->fd, file->name, offset, size, 1730Sigor@sysoev.ru POSIX_FADV_WILLNEED, err); 1740Sigor@sysoev.ru } 1750Sigor@sysoev.ru 1760Sigor@sysoev.ru #elif (NXT_HAVE_RDAHEAD) 1770Sigor@sysoev.ru 1780Sigor@sysoev.ru /* MacOSX fcntl(F_RDAHEAD). */ 1790Sigor@sysoev.ru 1800Sigor@sysoev.ru void 1810Sigor@sysoev.ru nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) 1820Sigor@sysoev.ru { 1830Sigor@sysoev.ru int ret; 1840Sigor@sysoev.ru u_char buf; 1850Sigor@sysoev.ru 1860Sigor@sysoev.ru ret = fcntl(file->fd, F_RDAHEAD, 1); 1870Sigor@sysoev.ru 1880Sigor@sysoev.ru nxt_thread_log_debug("fcntl(%FD, F_RDAHEAD, 1): %d", file->fd, ret); 1890Sigor@sysoev.ru 1900Sigor@sysoev.ru if (nxt_fast_path(ret != -1)) { 1910Sigor@sysoev.ru (void) nxt_file_read(file, &buf, 1, offset); 1920Sigor@sysoev.ru return; 1930Sigor@sysoev.ru } 1940Sigor@sysoev.ru 195*564Svbart@nginx.com nxt_thread_log_alert("fcntl(%FD, \"%FN\", F_RDAHEAD, 1) failed %E", 1960Sigor@sysoev.ru file->fd, file->name, nxt_errno); 1970Sigor@sysoev.ru } 1980Sigor@sysoev.ru 1990Sigor@sysoev.ru #else 2000Sigor@sysoev.ru 2010Sigor@sysoev.ru void 2020Sigor@sysoev.ru nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) 2030Sigor@sysoev.ru { 2040Sigor@sysoev.ru u_char buf; 2050Sigor@sysoev.ru 2060Sigor@sysoev.ru (void) nxt_file_read(file, &buf, 1, offset); 2070Sigor@sysoev.ru } 2080Sigor@sysoev.ru 2090Sigor@sysoev.ru #endif 2100Sigor@sysoev.ru 2110Sigor@sysoev.ru 2120Sigor@sysoev.ru nxt_int_t 2130Sigor@sysoev.ru nxt_file_info(nxt_file_t *file, nxt_file_info_t *fi) 2140Sigor@sysoev.ru { 2150Sigor@sysoev.ru int n; 2160Sigor@sysoev.ru 2170Sigor@sysoev.ru if (file->fd == NXT_FILE_INVALID) { 2180Sigor@sysoev.ru n = stat((char *) file->name, fi); 2190Sigor@sysoev.ru 2200Sigor@sysoev.ru file->error = (n != 0) ? nxt_errno : 0; 2210Sigor@sysoev.ru 2220Sigor@sysoev.ru nxt_thread_log_debug("stat(\"%FN)\": %d", file->name, n); 2230Sigor@sysoev.ru 2240Sigor@sysoev.ru if (n == 0) { 2250Sigor@sysoev.ru return NXT_OK; 2260Sigor@sysoev.ru } 2270Sigor@sysoev.ru 2280Sigor@sysoev.ru if (file->log_level != 0) { 2290Sigor@sysoev.ru nxt_thread_log_error(file->log_level, "stat(\"%FN\") failed %E", 2300Sigor@sysoev.ru file->name, file->error); 2310Sigor@sysoev.ru } 2320Sigor@sysoev.ru 2330Sigor@sysoev.ru return NXT_ERROR; 2340Sigor@sysoev.ru 2350Sigor@sysoev.ru } else { 2360Sigor@sysoev.ru n = fstat(file->fd, fi); 2370Sigor@sysoev.ru 2380Sigor@sysoev.ru file->error = (n != 0) ? nxt_errno : 0; 2390Sigor@sysoev.ru 2400Sigor@sysoev.ru nxt_thread_log_debug("fstat(%FD): %d", file->fd, n); 2410Sigor@sysoev.ru 2420Sigor@sysoev.ru if (n == 0) { 2430Sigor@sysoev.ru return NXT_OK; 2440Sigor@sysoev.ru } 2450Sigor@sysoev.ru 246*564Svbart@nginx.com /* Use NXT_LOG_ALERT because fstat() error on open file is strange. */ 2470Sigor@sysoev.ru 248*564Svbart@nginx.com nxt_thread_log_alert("fstat(%FD, \"%FN\") failed %E", 2490Sigor@sysoev.ru file->fd, file->name, file->error); 2500Sigor@sysoev.ru 2510Sigor@sysoev.ru return NXT_ERROR; 2520Sigor@sysoev.ru } 2530Sigor@sysoev.ru } 2540Sigor@sysoev.ru 2550Sigor@sysoev.ru 2560Sigor@sysoev.ru nxt_int_t 2570Sigor@sysoev.ru nxt_file_delete(nxt_file_name_t *name) 2580Sigor@sysoev.ru { 2590Sigor@sysoev.ru nxt_thread_log_debug("unlink(\"%FN\")", name); 2600Sigor@sysoev.ru 2610Sigor@sysoev.ru if (nxt_fast_path(unlink((char *) name) == 0)) { 2620Sigor@sysoev.ru return NXT_OK; 2630Sigor@sysoev.ru } 2640Sigor@sysoev.ru 2650Sigor@sysoev.ru nxt_thread_log_alert("unlink(\"%FN\") failed %E", name, nxt_errno); 2660Sigor@sysoev.ru 2670Sigor@sysoev.ru return NXT_ERROR; 2680Sigor@sysoev.ru } 2690Sigor@sysoev.ru 2700Sigor@sysoev.ru 2710Sigor@sysoev.ru nxt_int_t 2720Sigor@sysoev.ru nxt_file_set_access(nxt_file_name_t *name, nxt_file_access_t access) 2730Sigor@sysoev.ru { 2740Sigor@sysoev.ru if (nxt_fast_path(chmod((char *) name, access) == 0)) { 2750Sigor@sysoev.ru return NXT_OK; 2760Sigor@sysoev.ru } 2770Sigor@sysoev.ru 2780Sigor@sysoev.ru nxt_thread_log_alert("chmod(\"%FN\") failed %E", name, nxt_errno); 2790Sigor@sysoev.ru 2800Sigor@sysoev.ru return NXT_ERROR; 2810Sigor@sysoev.ru } 2820Sigor@sysoev.ru 2830Sigor@sysoev.ru 2840Sigor@sysoev.ru nxt_int_t 2850Sigor@sysoev.ru nxt_file_rename(nxt_file_name_t *old_name, nxt_file_name_t *new_name) 2860Sigor@sysoev.ru { 2870Sigor@sysoev.ru int ret; 2880Sigor@sysoev.ru 2890Sigor@sysoev.ru nxt_thread_log_debug("rename(\"%FN\", \"%FN\")", old_name, new_name); 2900Sigor@sysoev.ru 2910Sigor@sysoev.ru ret = rename((char *) old_name, (char *) new_name); 2920Sigor@sysoev.ru if (nxt_fast_path(ret == 0)) { 2930Sigor@sysoev.ru return NXT_OK; 2940Sigor@sysoev.ru } 2950Sigor@sysoev.ru 2960Sigor@sysoev.ru nxt_thread_log_alert("rename(\"%FN\", \"%FN\") failed %E", 2970Sigor@sysoev.ru old_name, new_name, nxt_errno); 2980Sigor@sysoev.ru 2990Sigor@sysoev.ru return NXT_ERROR; 3000Sigor@sysoev.ru } 3010Sigor@sysoev.ru 3020Sigor@sysoev.ru 3030Sigor@sysoev.ru /* 3040Sigor@sysoev.ru * ioctl(FIONBIO) sets a non-blocking mode using one syscall, 3050Sigor@sysoev.ru * thereas fcntl(F_SETFL, O_NONBLOCK) needs to learn the current state 3060Sigor@sysoev.ru * using fcntl(F_GETFL). 3070Sigor@sysoev.ru * 3080Sigor@sysoev.ru * ioctl() and fcntl() are syscalls at least in Linux 2.2, FreeBSD 2.x, 3090Sigor@sysoev.ru * and Solaris 7. 3100Sigor@sysoev.ru * 3110Sigor@sysoev.ru * Linux 2.4 uses BKL for ioctl() and fcntl(F_SETFL). 3120Sigor@sysoev.ru * Linux 2.6 does not use BKL. 3130Sigor@sysoev.ru */ 3140Sigor@sysoev.ru 3150Sigor@sysoev.ru #if (NXT_HAVE_FIONBIO) 3160Sigor@sysoev.ru 3170Sigor@sysoev.ru nxt_int_t 31813Sigor@sysoev.ru nxt_fd_nonblocking(nxt_task_t *task, nxt_fd_t fd) 3190Sigor@sysoev.ru { 3200Sigor@sysoev.ru int nb; 3210Sigor@sysoev.ru 3220Sigor@sysoev.ru nb = 1; 3230Sigor@sysoev.ru 3240Sigor@sysoev.ru if (nxt_fast_path(ioctl(fd, FIONBIO, &nb) != -1)) { 3250Sigor@sysoev.ru return NXT_OK; 3260Sigor@sysoev.ru } 3270Sigor@sysoev.ru 328*564Svbart@nginx.com nxt_alert(task, "ioctl(%d, FIONBIO) failed %E", fd, nxt_errno); 3290Sigor@sysoev.ru 3300Sigor@sysoev.ru return NXT_ERROR; 3310Sigor@sysoev.ru 3320Sigor@sysoev.ru } 3330Sigor@sysoev.ru 3340Sigor@sysoev.ru 3350Sigor@sysoev.ru nxt_int_t 33613Sigor@sysoev.ru nxt_fd_blocking(nxt_task_t *task, nxt_fd_t fd) 3370Sigor@sysoev.ru { 3380Sigor@sysoev.ru int nb; 3390Sigor@sysoev.ru 3400Sigor@sysoev.ru nb = 0; 3410Sigor@sysoev.ru 3420Sigor@sysoev.ru if (nxt_fast_path(ioctl(fd, FIONBIO, &nb) != -1)) { 3430Sigor@sysoev.ru return NXT_OK; 3440Sigor@sysoev.ru } 3450Sigor@sysoev.ru 346*564Svbart@nginx.com nxt_alert(task, "ioctl(%d, !FIONBIO) failed %E", fd, nxt_errno); 3470Sigor@sysoev.ru 3480Sigor@sysoev.ru return NXT_ERROR; 3490Sigor@sysoev.ru } 3500Sigor@sysoev.ru 3510Sigor@sysoev.ru #else /* !(NXT_HAVE_FIONBIO) */ 3520Sigor@sysoev.ru 3530Sigor@sysoev.ru nxt_int_t 35413Sigor@sysoev.ru nxt_fd_nonblocking(nxt_task_t *task, nxt_fd_t fd) 3550Sigor@sysoev.ru { 3560Sigor@sysoev.ru int flags; 3570Sigor@sysoev.ru 3580Sigor@sysoev.ru flags = fcntl(fd, F_GETFL); 3590Sigor@sysoev.ru 3600Sigor@sysoev.ru if (nxt_slow_path(flags == -1)) { 361*564Svbart@nginx.com nxt_alert(task, "fcntl(%d, F_GETFL) failed %E", fd, nxt_errno); 3620Sigor@sysoev.ru return NXT_ERROR; 3630Sigor@sysoev.ru } 3640Sigor@sysoev.ru 3650Sigor@sysoev.ru flags |= O_NONBLOCK; 3660Sigor@sysoev.ru 3670Sigor@sysoev.ru if (nxt_slow_path(fcntl(fd, F_SETFL, flags) == -1)) { 368*564Svbart@nginx.com nxt_alert(task, "fcntl(%d, F_SETFL, O_NONBLOCK) failed %E", 369*564Svbart@nginx.com fd, nxt_errno); 3700Sigor@sysoev.ru return NXT_ERROR; 3710Sigor@sysoev.ru } 3720Sigor@sysoev.ru 3730Sigor@sysoev.ru return NXT_OK; 3740Sigor@sysoev.ru } 3750Sigor@sysoev.ru 3760Sigor@sysoev.ru 3770Sigor@sysoev.ru nxt_int_t 37813Sigor@sysoev.ru nxt_fd_blocking(nxt_task_t *task, nxt_fd_t fd) 3790Sigor@sysoev.ru { 3800Sigor@sysoev.ru int flags; 3810Sigor@sysoev.ru 3820Sigor@sysoev.ru flags = fcntl(fd, F_GETFL); 3830Sigor@sysoev.ru 3840Sigor@sysoev.ru if (nxt_slow_path(flags == -1)) { 385*564Svbart@nginx.com nxt_alert(task, "fcntl(%d, F_GETFL) failed %E", fd, nxt_errno); 3860Sigor@sysoev.ru return NXT_ERROR; 3870Sigor@sysoev.ru } 3880Sigor@sysoev.ru 3890Sigor@sysoev.ru flags &= O_NONBLOCK; 3900Sigor@sysoev.ru 3910Sigor@sysoev.ru if (nxt_slow_path(fcntl(fd, F_SETFL, flags) == -1)) { 392*564Svbart@nginx.com nxt_alert(task, "fcntl(%d, F_SETFL, !O_NONBLOCK) failed %E", 393*564Svbart@nginx.com fd, nxt_errno); 3940Sigor@sysoev.ru return NXT_ERROR; 3950Sigor@sysoev.ru } 3960Sigor@sysoev.ru 3970Sigor@sysoev.ru return NXT_OK; 3980Sigor@sysoev.ru } 3990Sigor@sysoev.ru 4000Sigor@sysoev.ru #endif /* NXT_HAVE_FIONBIO */ 4010Sigor@sysoev.ru 4020Sigor@sysoev.ru 4030Sigor@sysoev.ru ssize_t 4040Sigor@sysoev.ru nxt_fd_write(nxt_fd_t fd, u_char *buf, size_t size) 4050Sigor@sysoev.ru { 4060Sigor@sysoev.ru ssize_t n; 4070Sigor@sysoev.ru nxt_err_t err; 4080Sigor@sysoev.ru 4090Sigor@sysoev.ru n = write(fd, buf, size); 4100Sigor@sysoev.ru 4110Sigor@sysoev.ru err = (n == -1) ? nxt_errno : 0; 4120Sigor@sysoev.ru 4130Sigor@sysoev.ru nxt_thread_log_debug("write(%FD, %p, %uz): %z", fd, buf, size, n); 4140Sigor@sysoev.ru 4150Sigor@sysoev.ru if (nxt_slow_path(n <= 0)) { 4160Sigor@sysoev.ru nxt_thread_log_alert("write(%FD) failed %E", fd, err); 4170Sigor@sysoev.ru } 4180Sigor@sysoev.ru 4190Sigor@sysoev.ru return n; 4200Sigor@sysoev.ru } 4210Sigor@sysoev.ru 4220Sigor@sysoev.ru 4230Sigor@sysoev.ru ssize_t 4240Sigor@sysoev.ru nxt_fd_read(nxt_fd_t fd, u_char *buf, size_t size) 4250Sigor@sysoev.ru { 4260Sigor@sysoev.ru ssize_t n; 4270Sigor@sysoev.ru nxt_err_t err; 4280Sigor@sysoev.ru 4290Sigor@sysoev.ru n = read(fd, buf, size); 4300Sigor@sysoev.ru 4310Sigor@sysoev.ru err = (n == -1) ? nxt_errno : 0; 4320Sigor@sysoev.ru 4330Sigor@sysoev.ru nxt_thread_log_debug("read(%FD, %p, %uz): %z", fd, buf, size, n); 4340Sigor@sysoev.ru 4350Sigor@sysoev.ru if (nxt_slow_path(n <= 0)) { 4360Sigor@sysoev.ru 4370Sigor@sysoev.ru if (err == NXT_EAGAIN) { 4380Sigor@sysoev.ru return 0; 4390Sigor@sysoev.ru } 4400Sigor@sysoev.ru 4410Sigor@sysoev.ru nxt_thread_log_alert("read(%FD) failed %E", fd, err); 4420Sigor@sysoev.ru } 4430Sigor@sysoev.ru 4440Sigor@sysoev.ru return n; 4450Sigor@sysoev.ru } 4460Sigor@sysoev.ru 4470Sigor@sysoev.ru 4480Sigor@sysoev.ru void 4490Sigor@sysoev.ru nxt_fd_close(nxt_fd_t fd) 4500Sigor@sysoev.ru { 4510Sigor@sysoev.ru nxt_thread_log_debug("close(%FD)", fd); 4520Sigor@sysoev.ru 4530Sigor@sysoev.ru if (nxt_slow_path(close(fd) != 0)) { 454*564Svbart@nginx.com nxt_thread_log_alert("close(%FD) failed %E", fd, nxt_errno); 4550Sigor@sysoev.ru } 4560Sigor@sysoev.ru } 4570Sigor@sysoev.ru 4580Sigor@sysoev.ru 4590Sigor@sysoev.ru /* 4600Sigor@sysoev.ru * nxt_file_redirect() redirects the file to the fd descriptor. 4610Sigor@sysoev.ru * Then the fd descriptor is closed. 4620Sigor@sysoev.ru */ 4630Sigor@sysoev.ru 4640Sigor@sysoev.ru nxt_int_t 4650Sigor@sysoev.ru nxt_file_redirect(nxt_file_t *file, nxt_fd_t fd) 4660Sigor@sysoev.ru { 4670Sigor@sysoev.ru nxt_thread_log_debug("dup2(%FD, %FD, \"%FN\")", fd, file->fd, file->name); 4680Sigor@sysoev.ru 4690Sigor@sysoev.ru if (dup2(fd, file->fd) == -1) { 470*564Svbart@nginx.com nxt_thread_log_alert("dup2(%FD, %FD, \"%FN\") failed %E", 4710Sigor@sysoev.ru fd, file->fd, file->name, nxt_errno); 4720Sigor@sysoev.ru return NXT_ERROR; 4730Sigor@sysoev.ru } 4740Sigor@sysoev.ru 4750Sigor@sysoev.ru if (close(fd) != 0) { 476*564Svbart@nginx.com nxt_thread_log_alert("close(%FD, \"%FN\") failed %E", 4770Sigor@sysoev.ru fd, file->name, nxt_errno); 4780Sigor@sysoev.ru return NXT_ERROR; 4790Sigor@sysoev.ru } 4800Sigor@sysoev.ru 4810Sigor@sysoev.ru return NXT_OK; 4820Sigor@sysoev.ru } 4830Sigor@sysoev.ru 4840Sigor@sysoev.ru 4850Sigor@sysoev.ru /* nxt_file_stderr() redirects the stderr descriptor to the file. */ 4860Sigor@sysoev.ru 4870Sigor@sysoev.ru nxt_int_t 4880Sigor@sysoev.ru nxt_file_stderr(nxt_file_t *file) 4890Sigor@sysoev.ru { 4900Sigor@sysoev.ru nxt_thread_log_debug("dup2(%FD, %FD, \"%FN\")", 4910Sigor@sysoev.ru file->fd, STDERR_FILENO, file->name); 4920Sigor@sysoev.ru 4930Sigor@sysoev.ru if (dup2(file->fd, STDERR_FILENO) != -1) { 4940Sigor@sysoev.ru return NXT_OK; 4950Sigor@sysoev.ru } 4960Sigor@sysoev.ru 497*564Svbart@nginx.com nxt_thread_log_alert("dup2(%FD, %FD, \"%FN\") failed %E", 498494Spluknet@nginx.com file->fd, STDERR_FILENO, file->name, nxt_errno); 4990Sigor@sysoev.ru 5000Sigor@sysoev.ru return NXT_ERROR; 5010Sigor@sysoev.ru } 5020Sigor@sysoev.ru 5030Sigor@sysoev.ru 5040Sigor@sysoev.ru nxt_int_t 5050Sigor@sysoev.ru nxt_stderr_start(void) 5060Sigor@sysoev.ru { 5070Sigor@sysoev.ru int flags, fd; 5080Sigor@sysoev.ru 5090Sigor@sysoev.ru flags = fcntl(nxt_stderr, F_GETFL); 5100Sigor@sysoev.ru 5110Sigor@sysoev.ru if (flags != -1) { 5120Sigor@sysoev.ru /* 5130Sigor@sysoev.ru * If the stderr output of a multithreaded application is 5140Sigor@sysoev.ru * redirected to a file: 5150Sigor@sysoev.ru * Linux, Solaris and MacOSX do not write atomically to the output; 5160Sigor@sysoev.ru * MacOSX besides adds zeroes to the output. 5170Sigor@sysoev.ru * O_APPEND fixes this. 5180Sigor@sysoev.ru */ 5190Sigor@sysoev.ru (void) fcntl(nxt_stderr, F_SETFL, flags | O_APPEND); 5200Sigor@sysoev.ru 5210Sigor@sysoev.ru } else { 5220Sigor@sysoev.ru /* 5230Sigor@sysoev.ru * The stderr descriptor is closed before application start. 5240Sigor@sysoev.ru * Reserve the stderr descriptor for future use. Errors are 5250Sigor@sysoev.ru * ignored because anyway they could be written nowhere. 5260Sigor@sysoev.ru */ 5270Sigor@sysoev.ru fd = open("/dev/null", O_WRONLY | O_APPEND); 5280Sigor@sysoev.ru 5290Sigor@sysoev.ru if (fd != -1) { 5300Sigor@sysoev.ru (void) dup2(fd, nxt_stderr); 5310Sigor@sysoev.ru 5320Sigor@sysoev.ru if (fd != nxt_stderr) { 5330Sigor@sysoev.ru (void) close(fd); 5340Sigor@sysoev.ru } 5350Sigor@sysoev.ru } 5360Sigor@sysoev.ru } 5370Sigor@sysoev.ru 5380Sigor@sysoev.ru return flags; 5390Sigor@sysoev.ru } 5400Sigor@sysoev.ru 5410Sigor@sysoev.ru 5420Sigor@sysoev.ru nxt_int_t 54313Sigor@sysoev.ru nxt_pipe_create(nxt_task_t *task, nxt_fd_t *pp, nxt_bool_t nbread, 54413Sigor@sysoev.ru nxt_bool_t nbwrite) 5450Sigor@sysoev.ru { 5460Sigor@sysoev.ru if (pipe(pp) != 0) { 547*564Svbart@nginx.com nxt_alert(task, "pipe() failed %E", nxt_errno); 5480Sigor@sysoev.ru 5490Sigor@sysoev.ru return NXT_ERROR; 5500Sigor@sysoev.ru } 5510Sigor@sysoev.ru 55213Sigor@sysoev.ru nxt_debug(task, "pipe(): %FD:%FD", pp[0], pp[1]); 5530Sigor@sysoev.ru 5540Sigor@sysoev.ru if (nbread) { 55513Sigor@sysoev.ru if (nxt_fd_nonblocking(task, pp[0]) != NXT_OK) { 5560Sigor@sysoev.ru return NXT_ERROR; 5570Sigor@sysoev.ru } 5580Sigor@sysoev.ru } 5590Sigor@sysoev.ru 5600Sigor@sysoev.ru if (nbwrite) { 56113Sigor@sysoev.ru if (nxt_fd_nonblocking(task, pp[1]) != NXT_OK) { 5620Sigor@sysoev.ru return NXT_ERROR; 5630Sigor@sysoev.ru } 5640Sigor@sysoev.ru } 5650Sigor@sysoev.ru 5660Sigor@sysoev.ru return NXT_OK; 5670Sigor@sysoev.ru } 5680Sigor@sysoev.ru 5690Sigor@sysoev.ru 5700Sigor@sysoev.ru void 57113Sigor@sysoev.ru nxt_pipe_close(nxt_task_t *task, nxt_fd_t *pp) 5720Sigor@sysoev.ru { 57313Sigor@sysoev.ru nxt_debug(task, "pipe close(%FD:%FD)", pp[0], pp[1]); 5740Sigor@sysoev.ru 5750Sigor@sysoev.ru if (close(pp[0]) != 0) { 576*564Svbart@nginx.com nxt_alert(task, "pipe close(%FD) failed %E", pp[0], nxt_errno); 5770Sigor@sysoev.ru } 5780Sigor@sysoev.ru 5790Sigor@sysoev.ru if (close(pp[1]) != 0) { 580*564Svbart@nginx.com nxt_alert(task, "pipe close(%FD) failed %E", pp[1], nxt_errno); 5810Sigor@sysoev.ru } 5820Sigor@sysoev.ru } 5830Sigor@sysoev.ru 5840Sigor@sysoev.ru 5850Sigor@sysoev.ru size_t 5860Sigor@sysoev.ru nxt_dir_current(char *buf, size_t len) 5870Sigor@sysoev.ru { 5880Sigor@sysoev.ru if (nxt_fast_path(getcwd(buf, len) != NULL)) { 5890Sigor@sysoev.ru return nxt_strlen(buf); 5900Sigor@sysoev.ru } 5910Sigor@sysoev.ru 5920Sigor@sysoev.ru nxt_thread_log_alert("getcwd(%uz) failed %E", len, nxt_errno); 5930Sigor@sysoev.ru 5940Sigor@sysoev.ru return 0; 5950Sigor@sysoev.ru } 596