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 45*1855Sz.hong@f5.com #if (NXT_HAVE_OPENAT2) 46*1855Sz.hong@f5.com 47*1855Sz.hong@f5.com nxt_int_t 48*1855Sz.hong@f5.com nxt_file_openat2(nxt_task_t *task, nxt_file_t *file, nxt_uint_t mode, 49*1855Sz.hong@f5.com nxt_uint_t create, nxt_file_access_t access, nxt_fd_t dfd, 50*1855Sz.hong@f5.com nxt_uint_t resolve) 51*1855Sz.hong@f5.com { 52*1855Sz.hong@f5.com struct open_how how; 53*1855Sz.hong@f5.com 54*1855Sz.hong@f5.com nxt_memzero(&how, sizeof(how)); 55*1855Sz.hong@f5.com 56*1855Sz.hong@f5.com /* O_NONBLOCK is to prevent blocking on FIFOs, special devices, etc. */ 57*1855Sz.hong@f5.com mode |= (O_NONBLOCK | create); 58*1855Sz.hong@f5.com 59*1855Sz.hong@f5.com how.flags = mode; 60*1855Sz.hong@f5.com how.mode = access; 61*1855Sz.hong@f5.com how.resolve = resolve; 62*1855Sz.hong@f5.com 63*1855Sz.hong@f5.com file->fd = syscall(SYS_openat2, dfd, file->name, &how, sizeof(how)); 64*1855Sz.hong@f5.com 65*1855Sz.hong@f5.com file->error = (file->fd == -1) ? nxt_errno : 0; 66*1855Sz.hong@f5.com 67*1855Sz.hong@f5.com #if (NXT_DEBUG) 68*1855Sz.hong@f5.com nxt_thread_time_update(task->thread); 69*1855Sz.hong@f5.com #endif 70*1855Sz.hong@f5.com 71*1855Sz.hong@f5.com nxt_debug(task, "openat2(%FD, \"%FN\"): %FD err:%d", dfd, file->name, 72*1855Sz.hong@f5.com file->fd, file->error); 73*1855Sz.hong@f5.com 74*1855Sz.hong@f5.com if (file->fd != -1) { 75*1855Sz.hong@f5.com return NXT_OK; 76*1855Sz.hong@f5.com } 77*1855Sz.hong@f5.com 78*1855Sz.hong@f5.com if (file->log_level != 0) { 79*1855Sz.hong@f5.com nxt_log(task, file->log_level, "openat2(%FD, \"%FN\") failed %E", dfd, 80*1855Sz.hong@f5.com file->name, file->error); 81*1855Sz.hong@f5.com } 82*1855Sz.hong@f5.com 83*1855Sz.hong@f5.com return NXT_ERROR; 84*1855Sz.hong@f5.com } 85*1855Sz.hong@f5.com 86*1855Sz.hong@f5.com #endif 87*1855Sz.hong@f5.com 88*1855Sz.hong@f5.com 890Sigor@sysoev.ru void 9020Sigor@sysoev.ru nxt_file_close(nxt_task_t *task, nxt_file_t *file) 910Sigor@sysoev.ru { 9220Sigor@sysoev.ru nxt_debug(task, "close(%FD)", file->fd); 930Sigor@sysoev.ru 940Sigor@sysoev.ru if (close(file->fd) != 0) { 95564Svbart@nginx.com nxt_alert(task, "close(%FD, \"%FN\") failed %E", 96564Svbart@nginx.com file->fd, file->name, nxt_errno); 970Sigor@sysoev.ru } 980Sigor@sysoev.ru } 990Sigor@sysoev.ru 1000Sigor@sysoev.ru 1010Sigor@sysoev.ru ssize_t 1020Sigor@sysoev.ru nxt_file_write(nxt_file_t *file, const u_char *buf, size_t size, 1030Sigor@sysoev.ru nxt_off_t offset) 1040Sigor@sysoev.ru { 1050Sigor@sysoev.ru ssize_t n; 1060Sigor@sysoev.ru 1070Sigor@sysoev.ru nxt_thread_debug(thr); 1080Sigor@sysoev.ru 1090Sigor@sysoev.ru n = pwrite(file->fd, buf, size, offset); 1100Sigor@sysoev.ru 1110Sigor@sysoev.ru file->error = (n < 0) ? nxt_errno : 0; 1120Sigor@sysoev.ru 1130Sigor@sysoev.ru nxt_thread_time_debug_update(thr); 1140Sigor@sysoev.ru 1150Sigor@sysoev.ru nxt_log_debug(thr->log, "pwrite(%FD, %p, %uz, %O): %z", 1160Sigor@sysoev.ru file->fd, buf, size, offset, n); 1170Sigor@sysoev.ru 1180Sigor@sysoev.ru if (nxt_fast_path(n >= 0)) { 1190Sigor@sysoev.ru return n; 1200Sigor@sysoev.ru } 1210Sigor@sysoev.ru 122564Svbart@nginx.com nxt_thread_log_alert("pwrite(%FD, \"%FN\", %p, %uz, %O) failed %E", 1230Sigor@sysoev.ru file->fd, file->name, buf, size, 1240Sigor@sysoev.ru offset, file->error); 1250Sigor@sysoev.ru 1260Sigor@sysoev.ru return NXT_ERROR; 1270Sigor@sysoev.ru } 1280Sigor@sysoev.ru 1290Sigor@sysoev.ru 1300Sigor@sysoev.ru ssize_t 1310Sigor@sysoev.ru nxt_file_read(nxt_file_t *file, u_char *buf, size_t size, nxt_off_t offset) 1320Sigor@sysoev.ru { 1330Sigor@sysoev.ru ssize_t n; 1340Sigor@sysoev.ru 1350Sigor@sysoev.ru nxt_thread_debug(thr); 1360Sigor@sysoev.ru 1370Sigor@sysoev.ru n = pread(file->fd, buf, size, offset); 1380Sigor@sysoev.ru 1390Sigor@sysoev.ru file->error = (n <= 0) ? nxt_errno : 0; 1400Sigor@sysoev.ru 1410Sigor@sysoev.ru nxt_thread_time_debug_update(thr); 1420Sigor@sysoev.ru 1430Sigor@sysoev.ru nxt_log_debug(thr->log, "pread(%FD, %p, %uz, %O): %z", 1440Sigor@sysoev.ru file->fd, buf, size, offset, n); 1450Sigor@sysoev.ru 1460Sigor@sysoev.ru if (nxt_fast_path(n >= 0)) { 1470Sigor@sysoev.ru return n; 1480Sigor@sysoev.ru } 1490Sigor@sysoev.ru 150564Svbart@nginx.com nxt_thread_log_alert("pread(%FD, \"%FN\", %p, %uz, %O) failed %E", 1510Sigor@sysoev.ru file->fd, file->name, buf, size, 1520Sigor@sysoev.ru offset, file->error); 1530Sigor@sysoev.ru 1540Sigor@sysoev.ru return NXT_ERROR; 1550Sigor@sysoev.ru } 1560Sigor@sysoev.ru 1570Sigor@sysoev.ru 1580Sigor@sysoev.ru #if (NXT_HAVE_READAHEAD) 1590Sigor@sysoev.ru 1600Sigor@sysoev.ru /* FreeBSD 8.0 fcntl(F_READAHEAD, size) enables read ahead up to the size. */ 1610Sigor@sysoev.ru 1620Sigor@sysoev.ru void 1630Sigor@sysoev.ru nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) 1640Sigor@sysoev.ru { 1650Sigor@sysoev.ru int ret; 1660Sigor@sysoev.ru u_char buf; 1670Sigor@sysoev.ru 1680Sigor@sysoev.ru ret = fcntl(file->fd, F_READAHEAD, (int) size); 1690Sigor@sysoev.ru 1700Sigor@sysoev.ru nxt_thread_log_debug("fcntl(%FD, F_READAHEAD, %uz): %d", 1710Sigor@sysoev.ru file->fd, size, ret); 1720Sigor@sysoev.ru 1730Sigor@sysoev.ru if (nxt_fast_path(ret != -1)) { 1740Sigor@sysoev.ru (void) nxt_file_read(file, &buf, 1, offset); 1750Sigor@sysoev.ru return; 1760Sigor@sysoev.ru } 1770Sigor@sysoev.ru 178564Svbart@nginx.com nxt_thread_log_alert("fcntl(%FD, \"%FN\", F_READAHEAD, %uz) failed %E", 1790Sigor@sysoev.ru file->fd, file->name, size, nxt_errno); 1800Sigor@sysoev.ru } 1810Sigor@sysoev.ru 1820Sigor@sysoev.ru #elif (NXT_HAVE_POSIX_FADVISE) 1830Sigor@sysoev.ru 1840Sigor@sysoev.ru /* 1850Sigor@sysoev.ru * POSIX_FADV_SEQUENTIAL 1860Sigor@sysoev.ru * Linux doubles the default readahead window size of a backing device 1870Sigor@sysoev.ru * which is usually 128K. 1880Sigor@sysoev.ru * 1890Sigor@sysoev.ru * FreeBSD does nothing. 1900Sigor@sysoev.ru * 1910Sigor@sysoev.ru * POSIX_FADV_WILLNEED 1920Sigor@sysoev.ru * Linux preloads synchronously up to 2M of specified file region in 1930Sigor@sysoev.ru * the kernel page cache. Linux-specific readahead(2) syscall does 1940Sigor@sysoev.ru * the same. Both operations are blocking despite posix_fadvise(2) 1950Sigor@sysoev.ru * claims the opposite. 1960Sigor@sysoev.ru * 1970Sigor@sysoev.ru * FreeBSD does nothing. 1980Sigor@sysoev.ru */ 1990Sigor@sysoev.ru 2000Sigor@sysoev.ru void 2010Sigor@sysoev.ru nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) 2020Sigor@sysoev.ru { 2030Sigor@sysoev.ru nxt_err_t err; 2040Sigor@sysoev.ru 2050Sigor@sysoev.ru err = posix_fadvise(file->fd, offset, size, POSIX_FADV_WILLNEED); 2060Sigor@sysoev.ru 2070Sigor@sysoev.ru nxt_thread_log_debug("posix_fadvise(%FD, \"%FN\", %O, %uz, %d): %d", 2080Sigor@sysoev.ru file->fd, file->name, offset, size, 2090Sigor@sysoev.ru POSIX_FADV_WILLNEED, err); 2100Sigor@sysoev.ru 2110Sigor@sysoev.ru if (nxt_fast_path(err == 0)) { 2120Sigor@sysoev.ru return; 2130Sigor@sysoev.ru } 2140Sigor@sysoev.ru 215564Svbart@nginx.com nxt_thread_log_alert("posix_fadvise(%FD, \"%FN\", %O, %uz, %d) failed %E", 2160Sigor@sysoev.ru file->fd, file->name, offset, size, 2170Sigor@sysoev.ru POSIX_FADV_WILLNEED, err); 2180Sigor@sysoev.ru } 2190Sigor@sysoev.ru 2200Sigor@sysoev.ru #elif (NXT_HAVE_RDAHEAD) 2210Sigor@sysoev.ru 2220Sigor@sysoev.ru /* MacOSX fcntl(F_RDAHEAD). */ 2230Sigor@sysoev.ru 2240Sigor@sysoev.ru void 2250Sigor@sysoev.ru nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) 2260Sigor@sysoev.ru { 2270Sigor@sysoev.ru int ret; 2280Sigor@sysoev.ru u_char buf; 2290Sigor@sysoev.ru 2300Sigor@sysoev.ru ret = fcntl(file->fd, F_RDAHEAD, 1); 2310Sigor@sysoev.ru 2320Sigor@sysoev.ru nxt_thread_log_debug("fcntl(%FD, F_RDAHEAD, 1): %d", file->fd, ret); 2330Sigor@sysoev.ru 2340Sigor@sysoev.ru if (nxt_fast_path(ret != -1)) { 2350Sigor@sysoev.ru (void) nxt_file_read(file, &buf, 1, offset); 2360Sigor@sysoev.ru return; 2370Sigor@sysoev.ru } 2380Sigor@sysoev.ru 239564Svbart@nginx.com nxt_thread_log_alert("fcntl(%FD, \"%FN\", F_RDAHEAD, 1) failed %E", 2400Sigor@sysoev.ru file->fd, file->name, nxt_errno); 2410Sigor@sysoev.ru } 2420Sigor@sysoev.ru 2430Sigor@sysoev.ru #else 2440Sigor@sysoev.ru 2450Sigor@sysoev.ru void 2460Sigor@sysoev.ru nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) 2470Sigor@sysoev.ru { 2480Sigor@sysoev.ru u_char buf; 2490Sigor@sysoev.ru 2500Sigor@sysoev.ru (void) nxt_file_read(file, &buf, 1, offset); 2510Sigor@sysoev.ru } 2520Sigor@sysoev.ru 2530Sigor@sysoev.ru #endif 2540Sigor@sysoev.ru 2550Sigor@sysoev.ru 2560Sigor@sysoev.ru nxt_int_t 2570Sigor@sysoev.ru nxt_file_info(nxt_file_t *file, nxt_file_info_t *fi) 2580Sigor@sysoev.ru { 2590Sigor@sysoev.ru int n; 2600Sigor@sysoev.ru 2610Sigor@sysoev.ru if (file->fd == NXT_FILE_INVALID) { 2620Sigor@sysoev.ru n = stat((char *) file->name, fi); 2630Sigor@sysoev.ru 2640Sigor@sysoev.ru file->error = (n != 0) ? nxt_errno : 0; 2650Sigor@sysoev.ru 2660Sigor@sysoev.ru nxt_thread_log_debug("stat(\"%FN)\": %d", file->name, n); 2670Sigor@sysoev.ru 2680Sigor@sysoev.ru if (n == 0) { 2690Sigor@sysoev.ru return NXT_OK; 2700Sigor@sysoev.ru } 2710Sigor@sysoev.ru 2720Sigor@sysoev.ru if (file->log_level != 0) { 2730Sigor@sysoev.ru nxt_thread_log_error(file->log_level, "stat(\"%FN\") failed %E", 2740Sigor@sysoev.ru file->name, file->error); 2750Sigor@sysoev.ru } 2760Sigor@sysoev.ru 2770Sigor@sysoev.ru return NXT_ERROR; 2780Sigor@sysoev.ru 2790Sigor@sysoev.ru } else { 2800Sigor@sysoev.ru n = fstat(file->fd, fi); 2810Sigor@sysoev.ru 2820Sigor@sysoev.ru file->error = (n != 0) ? nxt_errno : 0; 2830Sigor@sysoev.ru 2840Sigor@sysoev.ru nxt_thread_log_debug("fstat(%FD): %d", file->fd, n); 2850Sigor@sysoev.ru 2860Sigor@sysoev.ru if (n == 0) { 2870Sigor@sysoev.ru return NXT_OK; 2880Sigor@sysoev.ru } 2890Sigor@sysoev.ru 290564Svbart@nginx.com /* Use NXT_LOG_ALERT because fstat() error on open file is strange. */ 2910Sigor@sysoev.ru 292564Svbart@nginx.com nxt_thread_log_alert("fstat(%FD, \"%FN\") failed %E", 2930Sigor@sysoev.ru file->fd, file->name, file->error); 2940Sigor@sysoev.ru 2950Sigor@sysoev.ru return NXT_ERROR; 2960Sigor@sysoev.ru } 2970Sigor@sysoev.ru } 2980Sigor@sysoev.ru 2990Sigor@sysoev.ru 3000Sigor@sysoev.ru nxt_int_t 3010Sigor@sysoev.ru nxt_file_delete(nxt_file_name_t *name) 3020Sigor@sysoev.ru { 3030Sigor@sysoev.ru nxt_thread_log_debug("unlink(\"%FN\")", name); 3040Sigor@sysoev.ru 3050Sigor@sysoev.ru if (nxt_fast_path(unlink((char *) name) == 0)) { 3060Sigor@sysoev.ru return NXT_OK; 3070Sigor@sysoev.ru } 3080Sigor@sysoev.ru 3090Sigor@sysoev.ru nxt_thread_log_alert("unlink(\"%FN\") failed %E", name, nxt_errno); 3100Sigor@sysoev.ru 3110Sigor@sysoev.ru return NXT_ERROR; 3120Sigor@sysoev.ru } 3130Sigor@sysoev.ru 3140Sigor@sysoev.ru 3150Sigor@sysoev.ru nxt_int_t 3160Sigor@sysoev.ru nxt_file_set_access(nxt_file_name_t *name, nxt_file_access_t access) 3170Sigor@sysoev.ru { 3180Sigor@sysoev.ru if (nxt_fast_path(chmod((char *) name, access) == 0)) { 3190Sigor@sysoev.ru return NXT_OK; 3200Sigor@sysoev.ru } 3210Sigor@sysoev.ru 3220Sigor@sysoev.ru nxt_thread_log_alert("chmod(\"%FN\") failed %E", name, nxt_errno); 3230Sigor@sysoev.ru 3240Sigor@sysoev.ru return NXT_ERROR; 3250Sigor@sysoev.ru } 3260Sigor@sysoev.ru 3270Sigor@sysoev.ru 3280Sigor@sysoev.ru nxt_int_t 3290Sigor@sysoev.ru nxt_file_rename(nxt_file_name_t *old_name, nxt_file_name_t *new_name) 3300Sigor@sysoev.ru { 3310Sigor@sysoev.ru int ret; 3320Sigor@sysoev.ru 3330Sigor@sysoev.ru nxt_thread_log_debug("rename(\"%FN\", \"%FN\")", old_name, new_name); 3340Sigor@sysoev.ru 3350Sigor@sysoev.ru ret = rename((char *) old_name, (char *) new_name); 3360Sigor@sysoev.ru if (nxt_fast_path(ret == 0)) { 3370Sigor@sysoev.ru return NXT_OK; 3380Sigor@sysoev.ru } 3390Sigor@sysoev.ru 3400Sigor@sysoev.ru nxt_thread_log_alert("rename(\"%FN\", \"%FN\") failed %E", 3410Sigor@sysoev.ru old_name, new_name, nxt_errno); 3420Sigor@sysoev.ru 3430Sigor@sysoev.ru return NXT_ERROR; 3440Sigor@sysoev.ru } 3450Sigor@sysoev.ru 3460Sigor@sysoev.ru 3470Sigor@sysoev.ru /* 3480Sigor@sysoev.ru * ioctl(FIONBIO) sets a non-blocking mode using one syscall, 3490Sigor@sysoev.ru * thereas fcntl(F_SETFL, O_NONBLOCK) needs to learn the current state 3500Sigor@sysoev.ru * using fcntl(F_GETFL). 3510Sigor@sysoev.ru * 3520Sigor@sysoev.ru * ioctl() and fcntl() are syscalls at least in Linux 2.2, FreeBSD 2.x, 3530Sigor@sysoev.ru * and Solaris 7. 3540Sigor@sysoev.ru * 3550Sigor@sysoev.ru * Linux 2.4 uses BKL for ioctl() and fcntl(F_SETFL). 3560Sigor@sysoev.ru * Linux 2.6 does not use BKL. 3570Sigor@sysoev.ru */ 3580Sigor@sysoev.ru 3590Sigor@sysoev.ru #if (NXT_HAVE_FIONBIO) 3600Sigor@sysoev.ru 3610Sigor@sysoev.ru nxt_int_t 36213Sigor@sysoev.ru nxt_fd_nonblocking(nxt_task_t *task, nxt_fd_t fd) 3630Sigor@sysoev.ru { 3640Sigor@sysoev.ru int nb; 3650Sigor@sysoev.ru 3660Sigor@sysoev.ru nb = 1; 3670Sigor@sysoev.ru 3680Sigor@sysoev.ru if (nxt_fast_path(ioctl(fd, FIONBIO, &nb) != -1)) { 3690Sigor@sysoev.ru return NXT_OK; 3700Sigor@sysoev.ru } 3710Sigor@sysoev.ru 372564Svbart@nginx.com nxt_alert(task, "ioctl(%d, FIONBIO) failed %E", fd, nxt_errno); 3730Sigor@sysoev.ru 3740Sigor@sysoev.ru return NXT_ERROR; 3750Sigor@sysoev.ru 3760Sigor@sysoev.ru } 3770Sigor@sysoev.ru 3780Sigor@sysoev.ru 3790Sigor@sysoev.ru nxt_int_t 38013Sigor@sysoev.ru nxt_fd_blocking(nxt_task_t *task, nxt_fd_t fd) 3810Sigor@sysoev.ru { 3820Sigor@sysoev.ru int nb; 3830Sigor@sysoev.ru 3840Sigor@sysoev.ru nb = 0; 3850Sigor@sysoev.ru 3860Sigor@sysoev.ru if (nxt_fast_path(ioctl(fd, FIONBIO, &nb) != -1)) { 3870Sigor@sysoev.ru return NXT_OK; 3880Sigor@sysoev.ru } 3890Sigor@sysoev.ru 390564Svbart@nginx.com nxt_alert(task, "ioctl(%d, !FIONBIO) failed %E", fd, nxt_errno); 3910Sigor@sysoev.ru 3920Sigor@sysoev.ru return NXT_ERROR; 3930Sigor@sysoev.ru } 3940Sigor@sysoev.ru 3950Sigor@sysoev.ru #else /* !(NXT_HAVE_FIONBIO) */ 3960Sigor@sysoev.ru 3970Sigor@sysoev.ru nxt_int_t 39813Sigor@sysoev.ru nxt_fd_nonblocking(nxt_task_t *task, nxt_fd_t fd) 3990Sigor@sysoev.ru { 4000Sigor@sysoev.ru int flags; 4010Sigor@sysoev.ru 4020Sigor@sysoev.ru flags = fcntl(fd, F_GETFL); 4030Sigor@sysoev.ru 4040Sigor@sysoev.ru if (nxt_slow_path(flags == -1)) { 405564Svbart@nginx.com nxt_alert(task, "fcntl(%d, F_GETFL) failed %E", fd, nxt_errno); 4060Sigor@sysoev.ru return NXT_ERROR; 4070Sigor@sysoev.ru } 4080Sigor@sysoev.ru 4090Sigor@sysoev.ru flags |= O_NONBLOCK; 4100Sigor@sysoev.ru 4110Sigor@sysoev.ru if (nxt_slow_path(fcntl(fd, F_SETFL, flags) == -1)) { 412564Svbart@nginx.com nxt_alert(task, "fcntl(%d, F_SETFL, O_NONBLOCK) failed %E", 413564Svbart@nginx.com fd, nxt_errno); 4140Sigor@sysoev.ru return NXT_ERROR; 4150Sigor@sysoev.ru } 4160Sigor@sysoev.ru 4170Sigor@sysoev.ru return NXT_OK; 4180Sigor@sysoev.ru } 4190Sigor@sysoev.ru 4200Sigor@sysoev.ru 4210Sigor@sysoev.ru nxt_int_t 42213Sigor@sysoev.ru nxt_fd_blocking(nxt_task_t *task, nxt_fd_t fd) 4230Sigor@sysoev.ru { 4240Sigor@sysoev.ru int flags; 4250Sigor@sysoev.ru 4260Sigor@sysoev.ru flags = fcntl(fd, F_GETFL); 4270Sigor@sysoev.ru 4280Sigor@sysoev.ru if (nxt_slow_path(flags == -1)) { 429564Svbart@nginx.com nxt_alert(task, "fcntl(%d, F_GETFL) failed %E", fd, nxt_errno); 4300Sigor@sysoev.ru return NXT_ERROR; 4310Sigor@sysoev.ru } 4320Sigor@sysoev.ru 4330Sigor@sysoev.ru flags &= O_NONBLOCK; 4340Sigor@sysoev.ru 4350Sigor@sysoev.ru if (nxt_slow_path(fcntl(fd, F_SETFL, flags) == -1)) { 436564Svbart@nginx.com nxt_alert(task, "fcntl(%d, F_SETFL, !O_NONBLOCK) failed %E", 437564Svbart@nginx.com fd, nxt_errno); 4380Sigor@sysoev.ru return NXT_ERROR; 4390Sigor@sysoev.ru } 4400Sigor@sysoev.ru 4410Sigor@sysoev.ru return NXT_OK; 4420Sigor@sysoev.ru } 4430Sigor@sysoev.ru 4440Sigor@sysoev.ru #endif /* NXT_HAVE_FIONBIO */ 4450Sigor@sysoev.ru 4460Sigor@sysoev.ru 4470Sigor@sysoev.ru ssize_t 4480Sigor@sysoev.ru nxt_fd_write(nxt_fd_t fd, u_char *buf, size_t size) 4490Sigor@sysoev.ru { 4500Sigor@sysoev.ru ssize_t n; 4510Sigor@sysoev.ru nxt_err_t err; 4520Sigor@sysoev.ru 4530Sigor@sysoev.ru n = write(fd, buf, size); 4540Sigor@sysoev.ru 4550Sigor@sysoev.ru err = (n == -1) ? nxt_errno : 0; 4560Sigor@sysoev.ru 4570Sigor@sysoev.ru nxt_thread_log_debug("write(%FD, %p, %uz): %z", fd, buf, size, n); 4580Sigor@sysoev.ru 4590Sigor@sysoev.ru if (nxt_slow_path(n <= 0)) { 4600Sigor@sysoev.ru nxt_thread_log_alert("write(%FD) failed %E", fd, err); 4610Sigor@sysoev.ru } 4620Sigor@sysoev.ru 4630Sigor@sysoev.ru return n; 4640Sigor@sysoev.ru } 4650Sigor@sysoev.ru 4660Sigor@sysoev.ru 4670Sigor@sysoev.ru ssize_t 4680Sigor@sysoev.ru nxt_fd_read(nxt_fd_t fd, u_char *buf, size_t size) 4690Sigor@sysoev.ru { 4700Sigor@sysoev.ru ssize_t n; 4710Sigor@sysoev.ru nxt_err_t err; 4720Sigor@sysoev.ru 4730Sigor@sysoev.ru n = read(fd, buf, size); 4740Sigor@sysoev.ru 4750Sigor@sysoev.ru err = (n == -1) ? nxt_errno : 0; 4760Sigor@sysoev.ru 4770Sigor@sysoev.ru nxt_thread_log_debug("read(%FD, %p, %uz): %z", fd, buf, size, n); 4780Sigor@sysoev.ru 4790Sigor@sysoev.ru if (nxt_slow_path(n <= 0)) { 4800Sigor@sysoev.ru 4810Sigor@sysoev.ru if (err == NXT_EAGAIN) { 4820Sigor@sysoev.ru return 0; 4830Sigor@sysoev.ru } 4840Sigor@sysoev.ru 4850Sigor@sysoev.ru nxt_thread_log_alert("read(%FD) failed %E", fd, err); 4860Sigor@sysoev.ru } 4870Sigor@sysoev.ru 4880Sigor@sysoev.ru return n; 4890Sigor@sysoev.ru } 4900Sigor@sysoev.ru 4910Sigor@sysoev.ru 4920Sigor@sysoev.ru void 4930Sigor@sysoev.ru nxt_fd_close(nxt_fd_t fd) 4940Sigor@sysoev.ru { 4950Sigor@sysoev.ru nxt_thread_log_debug("close(%FD)", fd); 4960Sigor@sysoev.ru 4970Sigor@sysoev.ru if (nxt_slow_path(close(fd) != 0)) { 498564Svbart@nginx.com nxt_thread_log_alert("close(%FD) failed %E", fd, nxt_errno); 4990Sigor@sysoev.ru } 5000Sigor@sysoev.ru } 5010Sigor@sysoev.ru 5020Sigor@sysoev.ru 5030Sigor@sysoev.ru /* 5040Sigor@sysoev.ru * nxt_file_redirect() redirects the file to the fd descriptor. 5050Sigor@sysoev.ru * Then the fd descriptor is closed. 5060Sigor@sysoev.ru */ 5070Sigor@sysoev.ru 5080Sigor@sysoev.ru nxt_int_t 5090Sigor@sysoev.ru nxt_file_redirect(nxt_file_t *file, nxt_fd_t fd) 5100Sigor@sysoev.ru { 5110Sigor@sysoev.ru nxt_thread_log_debug("dup2(%FD, %FD, \"%FN\")", fd, file->fd, file->name); 5120Sigor@sysoev.ru 5130Sigor@sysoev.ru if (dup2(fd, file->fd) == -1) { 514564Svbart@nginx.com nxt_thread_log_alert("dup2(%FD, %FD, \"%FN\") failed %E", 5150Sigor@sysoev.ru fd, file->fd, file->name, nxt_errno); 5160Sigor@sysoev.ru return NXT_ERROR; 5170Sigor@sysoev.ru } 5180Sigor@sysoev.ru 5190Sigor@sysoev.ru if (close(fd) != 0) { 520564Svbart@nginx.com nxt_thread_log_alert("close(%FD, \"%FN\") failed %E", 5210Sigor@sysoev.ru fd, file->name, nxt_errno); 5220Sigor@sysoev.ru return NXT_ERROR; 5230Sigor@sysoev.ru } 5240Sigor@sysoev.ru 5250Sigor@sysoev.ru return NXT_OK; 5260Sigor@sysoev.ru } 5270Sigor@sysoev.ru 5280Sigor@sysoev.ru 5290Sigor@sysoev.ru /* nxt_file_stderr() redirects the stderr descriptor to the file. */ 5300Sigor@sysoev.ru 5310Sigor@sysoev.ru nxt_int_t 5320Sigor@sysoev.ru nxt_file_stderr(nxt_file_t *file) 5330Sigor@sysoev.ru { 5340Sigor@sysoev.ru nxt_thread_log_debug("dup2(%FD, %FD, \"%FN\")", 5350Sigor@sysoev.ru file->fd, STDERR_FILENO, file->name); 5360Sigor@sysoev.ru 5370Sigor@sysoev.ru if (dup2(file->fd, STDERR_FILENO) != -1) { 5380Sigor@sysoev.ru return NXT_OK; 5390Sigor@sysoev.ru } 5400Sigor@sysoev.ru 541564Svbart@nginx.com nxt_thread_log_alert("dup2(%FD, %FD, \"%FN\") failed %E", 542494Spluknet@nginx.com file->fd, STDERR_FILENO, file->name, nxt_errno); 5430Sigor@sysoev.ru 5440Sigor@sysoev.ru return NXT_ERROR; 5450Sigor@sysoev.ru } 5460Sigor@sysoev.ru 5470Sigor@sysoev.ru 5480Sigor@sysoev.ru nxt_int_t 5490Sigor@sysoev.ru nxt_stderr_start(void) 5500Sigor@sysoev.ru { 5510Sigor@sysoev.ru int flags, fd; 5520Sigor@sysoev.ru 5530Sigor@sysoev.ru flags = fcntl(nxt_stderr, F_GETFL); 5540Sigor@sysoev.ru 5550Sigor@sysoev.ru if (flags != -1) { 5560Sigor@sysoev.ru /* 5570Sigor@sysoev.ru * If the stderr output of a multithreaded application is 5580Sigor@sysoev.ru * redirected to a file: 5590Sigor@sysoev.ru * Linux, Solaris and MacOSX do not write atomically to the output; 5600Sigor@sysoev.ru * MacOSX besides adds zeroes to the output. 5610Sigor@sysoev.ru * O_APPEND fixes this. 5620Sigor@sysoev.ru */ 5630Sigor@sysoev.ru (void) fcntl(nxt_stderr, F_SETFL, flags | O_APPEND); 5640Sigor@sysoev.ru 5650Sigor@sysoev.ru } else { 5660Sigor@sysoev.ru /* 5670Sigor@sysoev.ru * The stderr descriptor is closed before application start. 5680Sigor@sysoev.ru * Reserve the stderr descriptor for future use. Errors are 5690Sigor@sysoev.ru * ignored because anyway they could be written nowhere. 5700Sigor@sysoev.ru */ 5710Sigor@sysoev.ru fd = open("/dev/null", O_WRONLY | O_APPEND); 5720Sigor@sysoev.ru 5730Sigor@sysoev.ru if (fd != -1) { 5740Sigor@sysoev.ru (void) dup2(fd, nxt_stderr); 5750Sigor@sysoev.ru 5760Sigor@sysoev.ru if (fd != nxt_stderr) { 5770Sigor@sysoev.ru (void) close(fd); 5780Sigor@sysoev.ru } 5790Sigor@sysoev.ru } 5800Sigor@sysoev.ru } 5810Sigor@sysoev.ru 5820Sigor@sysoev.ru return flags; 5830Sigor@sysoev.ru } 5840Sigor@sysoev.ru 5850Sigor@sysoev.ru 5860Sigor@sysoev.ru nxt_int_t 58713Sigor@sysoev.ru nxt_pipe_create(nxt_task_t *task, nxt_fd_t *pp, nxt_bool_t nbread, 58813Sigor@sysoev.ru nxt_bool_t nbwrite) 5890Sigor@sysoev.ru { 5900Sigor@sysoev.ru if (pipe(pp) != 0) { 591564Svbart@nginx.com nxt_alert(task, "pipe() failed %E", nxt_errno); 5920Sigor@sysoev.ru 5930Sigor@sysoev.ru return NXT_ERROR; 5940Sigor@sysoev.ru } 5950Sigor@sysoev.ru 59613Sigor@sysoev.ru nxt_debug(task, "pipe(): %FD:%FD", pp[0], pp[1]); 5970Sigor@sysoev.ru 5980Sigor@sysoev.ru if (nbread) { 59913Sigor@sysoev.ru if (nxt_fd_nonblocking(task, pp[0]) != NXT_OK) { 6000Sigor@sysoev.ru return NXT_ERROR; 6010Sigor@sysoev.ru } 6020Sigor@sysoev.ru } 6030Sigor@sysoev.ru 6040Sigor@sysoev.ru if (nbwrite) { 60513Sigor@sysoev.ru if (nxt_fd_nonblocking(task, pp[1]) != NXT_OK) { 6060Sigor@sysoev.ru return NXT_ERROR; 6070Sigor@sysoev.ru } 6080Sigor@sysoev.ru } 6090Sigor@sysoev.ru 6100Sigor@sysoev.ru return NXT_OK; 6110Sigor@sysoev.ru } 6120Sigor@sysoev.ru 6130Sigor@sysoev.ru 6140Sigor@sysoev.ru void 61513Sigor@sysoev.ru nxt_pipe_close(nxt_task_t *task, nxt_fd_t *pp) 6160Sigor@sysoev.ru { 61713Sigor@sysoev.ru nxt_debug(task, "pipe close(%FD:%FD)", pp[0], pp[1]); 6180Sigor@sysoev.ru 6190Sigor@sysoev.ru if (close(pp[0]) != 0) { 620564Svbart@nginx.com nxt_alert(task, "pipe close(%FD) failed %E", pp[0], nxt_errno); 6210Sigor@sysoev.ru } 6220Sigor@sysoev.ru 6230Sigor@sysoev.ru if (close(pp[1]) != 0) { 624564Svbart@nginx.com nxt_alert(task, "pipe close(%FD) failed %E", pp[1], nxt_errno); 6250Sigor@sysoev.ru } 6260Sigor@sysoev.ru } 6270Sigor@sysoev.ru 6280Sigor@sysoev.ru 6290Sigor@sysoev.ru size_t 6300Sigor@sysoev.ru nxt_dir_current(char *buf, size_t len) 6310Sigor@sysoev.ru { 6320Sigor@sysoev.ru if (nxt_fast_path(getcwd(buf, len) != NULL)) { 6330Sigor@sysoev.ru return nxt_strlen(buf); 6340Sigor@sysoev.ru } 6350Sigor@sysoev.ru 6360Sigor@sysoev.ru nxt_thread_log_alert("getcwd(%uz) failed %E", len, nxt_errno); 6370Sigor@sysoev.ru 6380Sigor@sysoev.ru return 0; 6390Sigor@sysoev.ru } 640