1*0Sigor@sysoev.ru 2*0Sigor@sysoev.ru /* 3*0Sigor@sysoev.ru * Copyright (C) Igor Sysoev 4*0Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 5*0Sigor@sysoev.ru */ 6*0Sigor@sysoev.ru 7*0Sigor@sysoev.ru #include <nxt_main.h> 8*0Sigor@sysoev.ru 9*0Sigor@sysoev.ru 10*0Sigor@sysoev.ru nxt_int_t 11*0Sigor@sysoev.ru nxt_file_open(nxt_file_t *file, nxt_uint_t mode, nxt_uint_t create, 12*0Sigor@sysoev.ru nxt_file_access_t access) 13*0Sigor@sysoev.ru { 14*0Sigor@sysoev.ru nxt_thread_debug(thr); 15*0Sigor@sysoev.ru 16*0Sigor@sysoev.ru #ifdef __CYGWIN__ 17*0Sigor@sysoev.ru mode |= O_BINARY; 18*0Sigor@sysoev.ru #endif 19*0Sigor@sysoev.ru 20*0Sigor@sysoev.ru /* O_NONBLOCK is to prevent blocking on FIFOs, special devices, etc. */ 21*0Sigor@sysoev.ru mode |= (O_NONBLOCK | create); 22*0Sigor@sysoev.ru 23*0Sigor@sysoev.ru file->fd = open((char *) file->name, mode, access); 24*0Sigor@sysoev.ru 25*0Sigor@sysoev.ru file->error = (file->fd == -1) ? nxt_errno : 0; 26*0Sigor@sysoev.ru 27*0Sigor@sysoev.ru nxt_thread_time_debug_update(thr); 28*0Sigor@sysoev.ru 29*0Sigor@sysoev.ru nxt_log_debug(thr->log, "open(\"%FN\", 0x%uXi, 0x%uXi): %FD err:%d", 30*0Sigor@sysoev.ru file->name, mode, access, file->fd, file->error); 31*0Sigor@sysoev.ru 32*0Sigor@sysoev.ru if (file->fd != -1) { 33*0Sigor@sysoev.ru return NXT_OK; 34*0Sigor@sysoev.ru } 35*0Sigor@sysoev.ru 36*0Sigor@sysoev.ru if (file->log_level != 0) { 37*0Sigor@sysoev.ru nxt_thread_log_error(file->log_level, "open(\"%FN\") failed %E", 38*0Sigor@sysoev.ru file->name, file->error); 39*0Sigor@sysoev.ru } 40*0Sigor@sysoev.ru 41*0Sigor@sysoev.ru return NXT_ERROR; 42*0Sigor@sysoev.ru } 43*0Sigor@sysoev.ru 44*0Sigor@sysoev.ru 45*0Sigor@sysoev.ru void 46*0Sigor@sysoev.ru nxt_file_close(nxt_file_t *file) 47*0Sigor@sysoev.ru { 48*0Sigor@sysoev.ru nxt_thread_log_debug("close(%FD)", file->fd); 49*0Sigor@sysoev.ru 50*0Sigor@sysoev.ru if (close(file->fd) != 0) { 51*0Sigor@sysoev.ru nxt_thread_log_error(NXT_LOG_CRIT, "close(%FD, \"%FN\") failed %E", 52*0Sigor@sysoev.ru file->fd, file->name, nxt_errno); 53*0Sigor@sysoev.ru } 54*0Sigor@sysoev.ru } 55*0Sigor@sysoev.ru 56*0Sigor@sysoev.ru 57*0Sigor@sysoev.ru ssize_t 58*0Sigor@sysoev.ru nxt_file_write(nxt_file_t *file, const u_char *buf, size_t size, 59*0Sigor@sysoev.ru nxt_off_t offset) 60*0Sigor@sysoev.ru { 61*0Sigor@sysoev.ru ssize_t n; 62*0Sigor@sysoev.ru 63*0Sigor@sysoev.ru nxt_thread_debug(thr); 64*0Sigor@sysoev.ru 65*0Sigor@sysoev.ru n = pwrite(file->fd, buf, size, offset); 66*0Sigor@sysoev.ru 67*0Sigor@sysoev.ru file->error = (n < 0) ? nxt_errno : 0; 68*0Sigor@sysoev.ru 69*0Sigor@sysoev.ru nxt_thread_time_debug_update(thr); 70*0Sigor@sysoev.ru 71*0Sigor@sysoev.ru nxt_log_debug(thr->log, "pwrite(%FD, %p, %uz, %O): %z", 72*0Sigor@sysoev.ru file->fd, buf, size, offset, n); 73*0Sigor@sysoev.ru 74*0Sigor@sysoev.ru if (nxt_fast_path(n >= 0)) { 75*0Sigor@sysoev.ru return n; 76*0Sigor@sysoev.ru } 77*0Sigor@sysoev.ru 78*0Sigor@sysoev.ru nxt_thread_log_error(NXT_LOG_CRIT, 79*0Sigor@sysoev.ru "pwrite(%FD, \"%FN\", %p, %uz, %O) failed %E", 80*0Sigor@sysoev.ru file->fd, file->name, buf, size, 81*0Sigor@sysoev.ru offset, file->error); 82*0Sigor@sysoev.ru 83*0Sigor@sysoev.ru return NXT_ERROR; 84*0Sigor@sysoev.ru } 85*0Sigor@sysoev.ru 86*0Sigor@sysoev.ru 87*0Sigor@sysoev.ru ssize_t 88*0Sigor@sysoev.ru nxt_file_read(nxt_file_t *file, u_char *buf, size_t size, nxt_off_t offset) 89*0Sigor@sysoev.ru { 90*0Sigor@sysoev.ru ssize_t n; 91*0Sigor@sysoev.ru 92*0Sigor@sysoev.ru nxt_thread_debug(thr); 93*0Sigor@sysoev.ru 94*0Sigor@sysoev.ru n = pread(file->fd, buf, size, offset); 95*0Sigor@sysoev.ru 96*0Sigor@sysoev.ru file->error = (n <= 0) ? nxt_errno : 0; 97*0Sigor@sysoev.ru 98*0Sigor@sysoev.ru nxt_thread_time_debug_update(thr); 99*0Sigor@sysoev.ru 100*0Sigor@sysoev.ru nxt_log_debug(thr->log, "pread(%FD, %p, %uz, %O): %z", 101*0Sigor@sysoev.ru file->fd, buf, size, offset, n); 102*0Sigor@sysoev.ru 103*0Sigor@sysoev.ru if (nxt_fast_path(n >= 0)) { 104*0Sigor@sysoev.ru return n; 105*0Sigor@sysoev.ru } 106*0Sigor@sysoev.ru 107*0Sigor@sysoev.ru nxt_thread_log_error(NXT_LOG_CRIT, 108*0Sigor@sysoev.ru "pread(%FD, \"%FN\", %p, %uz, %O) failed %E", 109*0Sigor@sysoev.ru file->fd, file->name, buf, size, 110*0Sigor@sysoev.ru offset, file->error); 111*0Sigor@sysoev.ru 112*0Sigor@sysoev.ru return NXT_ERROR; 113*0Sigor@sysoev.ru } 114*0Sigor@sysoev.ru 115*0Sigor@sysoev.ru 116*0Sigor@sysoev.ru #if (NXT_HAVE_READAHEAD) 117*0Sigor@sysoev.ru 118*0Sigor@sysoev.ru /* FreeBSD 8.0 fcntl(F_READAHEAD, size) enables read ahead up to the size. */ 119*0Sigor@sysoev.ru 120*0Sigor@sysoev.ru void 121*0Sigor@sysoev.ru nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) 122*0Sigor@sysoev.ru { 123*0Sigor@sysoev.ru int ret; 124*0Sigor@sysoev.ru u_char buf; 125*0Sigor@sysoev.ru 126*0Sigor@sysoev.ru ret = fcntl(file->fd, F_READAHEAD, (int) size); 127*0Sigor@sysoev.ru 128*0Sigor@sysoev.ru nxt_thread_log_debug("fcntl(%FD, F_READAHEAD, %uz): %d", 129*0Sigor@sysoev.ru file->fd, size, ret); 130*0Sigor@sysoev.ru 131*0Sigor@sysoev.ru if (nxt_fast_path(ret != -1)) { 132*0Sigor@sysoev.ru (void) nxt_file_read(file, &buf, 1, offset); 133*0Sigor@sysoev.ru return; 134*0Sigor@sysoev.ru } 135*0Sigor@sysoev.ru 136*0Sigor@sysoev.ru nxt_thread_log_error(NXT_LOG_CRIT, 137*0Sigor@sysoev.ru "fcntl(%FD, \"%FN\", F_READAHEAD, %uz) failed %E", 138*0Sigor@sysoev.ru file->fd, file->name, size, nxt_errno); 139*0Sigor@sysoev.ru } 140*0Sigor@sysoev.ru 141*0Sigor@sysoev.ru #elif (NXT_HAVE_POSIX_FADVISE) 142*0Sigor@sysoev.ru 143*0Sigor@sysoev.ru /* 144*0Sigor@sysoev.ru * POSIX_FADV_SEQUENTIAL 145*0Sigor@sysoev.ru * Linux doubles the default readahead window size of a backing device 146*0Sigor@sysoev.ru * which is usually 128K. 147*0Sigor@sysoev.ru * 148*0Sigor@sysoev.ru * FreeBSD does nothing. 149*0Sigor@sysoev.ru * 150*0Sigor@sysoev.ru * POSIX_FADV_WILLNEED 151*0Sigor@sysoev.ru * Linux preloads synchronously up to 2M of specified file region in 152*0Sigor@sysoev.ru * the kernel page cache. Linux-specific readahead(2) syscall does 153*0Sigor@sysoev.ru * the same. Both operations are blocking despite posix_fadvise(2) 154*0Sigor@sysoev.ru * claims the opposite. 155*0Sigor@sysoev.ru * 156*0Sigor@sysoev.ru * FreeBSD does nothing. 157*0Sigor@sysoev.ru */ 158*0Sigor@sysoev.ru 159*0Sigor@sysoev.ru void 160*0Sigor@sysoev.ru nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) 161*0Sigor@sysoev.ru { 162*0Sigor@sysoev.ru nxt_err_t err; 163*0Sigor@sysoev.ru 164*0Sigor@sysoev.ru err = posix_fadvise(file->fd, offset, size, POSIX_FADV_WILLNEED); 165*0Sigor@sysoev.ru 166*0Sigor@sysoev.ru nxt_thread_log_debug("posix_fadvise(%FD, \"%FN\", %O, %uz, %d): %d", 167*0Sigor@sysoev.ru file->fd, file->name, offset, size, 168*0Sigor@sysoev.ru POSIX_FADV_WILLNEED, err); 169*0Sigor@sysoev.ru 170*0Sigor@sysoev.ru if (nxt_fast_path(err == 0)) { 171*0Sigor@sysoev.ru return; 172*0Sigor@sysoev.ru } 173*0Sigor@sysoev.ru 174*0Sigor@sysoev.ru nxt_thread_log_error(NXT_LOG_CRIT, 175*0Sigor@sysoev.ru "posix_fadvise(%FD, \"%FN\", %O, %uz, %d) failed %E", 176*0Sigor@sysoev.ru file->fd, file->name, offset, size, 177*0Sigor@sysoev.ru POSIX_FADV_WILLNEED, err); 178*0Sigor@sysoev.ru } 179*0Sigor@sysoev.ru 180*0Sigor@sysoev.ru #elif (NXT_HAVE_RDAHEAD) 181*0Sigor@sysoev.ru 182*0Sigor@sysoev.ru /* MacOSX fcntl(F_RDAHEAD). */ 183*0Sigor@sysoev.ru 184*0Sigor@sysoev.ru void 185*0Sigor@sysoev.ru nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) 186*0Sigor@sysoev.ru { 187*0Sigor@sysoev.ru int ret; 188*0Sigor@sysoev.ru u_char buf; 189*0Sigor@sysoev.ru 190*0Sigor@sysoev.ru ret = fcntl(file->fd, F_RDAHEAD, 1); 191*0Sigor@sysoev.ru 192*0Sigor@sysoev.ru nxt_thread_log_debug("fcntl(%FD, F_RDAHEAD, 1): %d", file->fd, ret); 193*0Sigor@sysoev.ru 194*0Sigor@sysoev.ru if (nxt_fast_path(ret != -1)) { 195*0Sigor@sysoev.ru (void) nxt_file_read(file, &buf, 1, offset); 196*0Sigor@sysoev.ru return; 197*0Sigor@sysoev.ru } 198*0Sigor@sysoev.ru 199*0Sigor@sysoev.ru nxt_thread_log_error(NXT_LOG_CRIT, 200*0Sigor@sysoev.ru "fcntl(%FD, \"%FN\", F_RDAHEAD, 1) failed %E", 201*0Sigor@sysoev.ru file->fd, file->name, nxt_errno); 202*0Sigor@sysoev.ru } 203*0Sigor@sysoev.ru 204*0Sigor@sysoev.ru #else 205*0Sigor@sysoev.ru 206*0Sigor@sysoev.ru void 207*0Sigor@sysoev.ru nxt_file_read_ahead(nxt_file_t *file, nxt_off_t offset, size_t size) 208*0Sigor@sysoev.ru { 209*0Sigor@sysoev.ru u_char buf; 210*0Sigor@sysoev.ru 211*0Sigor@sysoev.ru (void) nxt_file_read(file, &buf, 1, offset); 212*0Sigor@sysoev.ru } 213*0Sigor@sysoev.ru 214*0Sigor@sysoev.ru #endif 215*0Sigor@sysoev.ru 216*0Sigor@sysoev.ru 217*0Sigor@sysoev.ru nxt_int_t 218*0Sigor@sysoev.ru nxt_file_info(nxt_file_t *file, nxt_file_info_t *fi) 219*0Sigor@sysoev.ru { 220*0Sigor@sysoev.ru int n; 221*0Sigor@sysoev.ru 222*0Sigor@sysoev.ru if (file->fd == NXT_FILE_INVALID) { 223*0Sigor@sysoev.ru n = stat((char *) file->name, fi); 224*0Sigor@sysoev.ru 225*0Sigor@sysoev.ru file->error = (n != 0) ? nxt_errno : 0; 226*0Sigor@sysoev.ru 227*0Sigor@sysoev.ru nxt_thread_log_debug("stat(\"%FN)\": %d", file->name, n); 228*0Sigor@sysoev.ru 229*0Sigor@sysoev.ru if (n == 0) { 230*0Sigor@sysoev.ru return NXT_OK; 231*0Sigor@sysoev.ru } 232*0Sigor@sysoev.ru 233*0Sigor@sysoev.ru if (file->log_level != 0) { 234*0Sigor@sysoev.ru nxt_thread_log_error(file->log_level, "stat(\"%FN\") failed %E", 235*0Sigor@sysoev.ru file->name, file->error); 236*0Sigor@sysoev.ru } 237*0Sigor@sysoev.ru 238*0Sigor@sysoev.ru return NXT_ERROR; 239*0Sigor@sysoev.ru 240*0Sigor@sysoev.ru } else { 241*0Sigor@sysoev.ru n = fstat(file->fd, fi); 242*0Sigor@sysoev.ru 243*0Sigor@sysoev.ru file->error = (n != 0) ? nxt_errno : 0; 244*0Sigor@sysoev.ru 245*0Sigor@sysoev.ru nxt_thread_log_debug("fstat(%FD): %d", file->fd, n); 246*0Sigor@sysoev.ru 247*0Sigor@sysoev.ru if (n == 0) { 248*0Sigor@sysoev.ru return NXT_OK; 249*0Sigor@sysoev.ru } 250*0Sigor@sysoev.ru 251*0Sigor@sysoev.ru /* Use NXT_LOG_CRIT because fstat() error on open file is strange. */ 252*0Sigor@sysoev.ru 253*0Sigor@sysoev.ru nxt_thread_log_error(NXT_LOG_CRIT, "fstat(%FD, \"%FN\") failed %E", 254*0Sigor@sysoev.ru file->fd, file->name, file->error); 255*0Sigor@sysoev.ru 256*0Sigor@sysoev.ru return NXT_ERROR; 257*0Sigor@sysoev.ru } 258*0Sigor@sysoev.ru } 259*0Sigor@sysoev.ru 260*0Sigor@sysoev.ru 261*0Sigor@sysoev.ru nxt_int_t 262*0Sigor@sysoev.ru nxt_file_delete(nxt_file_name_t *name) 263*0Sigor@sysoev.ru { 264*0Sigor@sysoev.ru nxt_thread_log_debug("unlink(\"%FN\")", name); 265*0Sigor@sysoev.ru 266*0Sigor@sysoev.ru if (nxt_fast_path(unlink((char *) name) == 0)) { 267*0Sigor@sysoev.ru return NXT_OK; 268*0Sigor@sysoev.ru } 269*0Sigor@sysoev.ru 270*0Sigor@sysoev.ru nxt_thread_log_alert("unlink(\"%FN\") failed %E", name, nxt_errno); 271*0Sigor@sysoev.ru 272*0Sigor@sysoev.ru return NXT_ERROR; 273*0Sigor@sysoev.ru } 274*0Sigor@sysoev.ru 275*0Sigor@sysoev.ru 276*0Sigor@sysoev.ru nxt_int_t 277*0Sigor@sysoev.ru nxt_file_set_access(nxt_file_name_t *name, nxt_file_access_t access) 278*0Sigor@sysoev.ru { 279*0Sigor@sysoev.ru if (nxt_fast_path(chmod((char *) name, access) == 0)) { 280*0Sigor@sysoev.ru return NXT_OK; 281*0Sigor@sysoev.ru } 282*0Sigor@sysoev.ru 283*0Sigor@sysoev.ru nxt_thread_log_alert("chmod(\"%FN\") failed %E", name, nxt_errno); 284*0Sigor@sysoev.ru 285*0Sigor@sysoev.ru return NXT_ERROR; 286*0Sigor@sysoev.ru } 287*0Sigor@sysoev.ru 288*0Sigor@sysoev.ru 289*0Sigor@sysoev.ru nxt_int_t 290*0Sigor@sysoev.ru nxt_file_rename(nxt_file_name_t *old_name, nxt_file_name_t *new_name) 291*0Sigor@sysoev.ru { 292*0Sigor@sysoev.ru int ret; 293*0Sigor@sysoev.ru 294*0Sigor@sysoev.ru nxt_thread_log_debug("rename(\"%FN\", \"%FN\")", old_name, new_name); 295*0Sigor@sysoev.ru 296*0Sigor@sysoev.ru ret = rename((char *) old_name, (char *) new_name); 297*0Sigor@sysoev.ru if (nxt_fast_path(ret == 0)) { 298*0Sigor@sysoev.ru return NXT_OK; 299*0Sigor@sysoev.ru } 300*0Sigor@sysoev.ru 301*0Sigor@sysoev.ru nxt_thread_log_alert("rename(\"%FN\", \"%FN\") failed %E", 302*0Sigor@sysoev.ru old_name, new_name, nxt_errno); 303*0Sigor@sysoev.ru 304*0Sigor@sysoev.ru return NXT_ERROR; 305*0Sigor@sysoev.ru } 306*0Sigor@sysoev.ru 307*0Sigor@sysoev.ru 308*0Sigor@sysoev.ru /* 309*0Sigor@sysoev.ru * ioctl(FIONBIO) sets a non-blocking mode using one syscall, 310*0Sigor@sysoev.ru * thereas fcntl(F_SETFL, O_NONBLOCK) needs to learn the current state 311*0Sigor@sysoev.ru * using fcntl(F_GETFL). 312*0Sigor@sysoev.ru * 313*0Sigor@sysoev.ru * ioctl() and fcntl() are syscalls at least in Linux 2.2, FreeBSD 2.x, 314*0Sigor@sysoev.ru * and Solaris 7. 315*0Sigor@sysoev.ru * 316*0Sigor@sysoev.ru * Linux 2.4 uses BKL for ioctl() and fcntl(F_SETFL). 317*0Sigor@sysoev.ru * Linux 2.6 does not use BKL. 318*0Sigor@sysoev.ru */ 319*0Sigor@sysoev.ru 320*0Sigor@sysoev.ru #if (NXT_HAVE_FIONBIO) 321*0Sigor@sysoev.ru 322*0Sigor@sysoev.ru nxt_int_t 323*0Sigor@sysoev.ru nxt_fd_nonblocking(nxt_fd_t fd) 324*0Sigor@sysoev.ru { 325*0Sigor@sysoev.ru int nb; 326*0Sigor@sysoev.ru 327*0Sigor@sysoev.ru nb = 1; 328*0Sigor@sysoev.ru 329*0Sigor@sysoev.ru if (nxt_fast_path(ioctl(fd, FIONBIO, &nb) != -1)) { 330*0Sigor@sysoev.ru return NXT_OK; 331*0Sigor@sysoev.ru } 332*0Sigor@sysoev.ru 333*0Sigor@sysoev.ru nxt_thread_log_alert("ioctl(%d, FIONBIO) failed %E", fd, nxt_errno); 334*0Sigor@sysoev.ru 335*0Sigor@sysoev.ru return NXT_ERROR; 336*0Sigor@sysoev.ru 337*0Sigor@sysoev.ru } 338*0Sigor@sysoev.ru 339*0Sigor@sysoev.ru 340*0Sigor@sysoev.ru nxt_int_t 341*0Sigor@sysoev.ru nxt_fd_blocking(nxt_fd_t fd) 342*0Sigor@sysoev.ru { 343*0Sigor@sysoev.ru int nb; 344*0Sigor@sysoev.ru 345*0Sigor@sysoev.ru nb = 0; 346*0Sigor@sysoev.ru 347*0Sigor@sysoev.ru if (nxt_fast_path(ioctl(fd, FIONBIO, &nb) != -1)) { 348*0Sigor@sysoev.ru return NXT_OK; 349*0Sigor@sysoev.ru } 350*0Sigor@sysoev.ru 351*0Sigor@sysoev.ru nxt_thread_log_alert("ioctl(%d, !FIONBIO) failed %E", fd, nxt_errno); 352*0Sigor@sysoev.ru 353*0Sigor@sysoev.ru return NXT_ERROR; 354*0Sigor@sysoev.ru } 355*0Sigor@sysoev.ru 356*0Sigor@sysoev.ru #else /* !(NXT_HAVE_FIONBIO) */ 357*0Sigor@sysoev.ru 358*0Sigor@sysoev.ru nxt_int_t 359*0Sigor@sysoev.ru nxt_fd_nonblocking(nxt_fd_t fd) 360*0Sigor@sysoev.ru { 361*0Sigor@sysoev.ru int flags; 362*0Sigor@sysoev.ru 363*0Sigor@sysoev.ru flags = fcntl(fd, F_GETFL); 364*0Sigor@sysoev.ru 365*0Sigor@sysoev.ru if (nxt_slow_path(flags == -1)) { 366*0Sigor@sysoev.ru nxt_thread_log_alert("fcntl(%d, F_GETFL) failed %E", fd, nxt_errno); 367*0Sigor@sysoev.ru return NXT_ERROR; 368*0Sigor@sysoev.ru } 369*0Sigor@sysoev.ru 370*0Sigor@sysoev.ru flags |= O_NONBLOCK; 371*0Sigor@sysoev.ru 372*0Sigor@sysoev.ru if (nxt_slow_path(fcntl(fd, F_SETFL, flags) == -1)) { 373*0Sigor@sysoev.ru nxt_thread_log_alert("fcntl(%d, F_SETFL, O_NONBLOCK) failed %E", 374*0Sigor@sysoev.ru fd, nxt_errno); 375*0Sigor@sysoev.ru return NXT_ERROR; 376*0Sigor@sysoev.ru } 377*0Sigor@sysoev.ru 378*0Sigor@sysoev.ru return NXT_OK; 379*0Sigor@sysoev.ru } 380*0Sigor@sysoev.ru 381*0Sigor@sysoev.ru 382*0Sigor@sysoev.ru nxt_int_t 383*0Sigor@sysoev.ru nxt_fd_blocking(nxt_fd_t fd) 384*0Sigor@sysoev.ru { 385*0Sigor@sysoev.ru int flags; 386*0Sigor@sysoev.ru 387*0Sigor@sysoev.ru flags = fcntl(fd, F_GETFL); 388*0Sigor@sysoev.ru 389*0Sigor@sysoev.ru if (nxt_slow_path(flags == -1)) { 390*0Sigor@sysoev.ru nxt_thread_log_alert("fcntl(%d, F_GETFL) failed %E", 391*0Sigor@sysoev.ru fd, nxt_errno); 392*0Sigor@sysoev.ru return NXT_ERROR; 393*0Sigor@sysoev.ru } 394*0Sigor@sysoev.ru 395*0Sigor@sysoev.ru flags &= O_NONBLOCK; 396*0Sigor@sysoev.ru 397*0Sigor@sysoev.ru if (nxt_slow_path(fcntl(fd, F_SETFL, flags) == -1)) { 398*0Sigor@sysoev.ru nxt_thread_log_alert("fcntl(%d, F_SETFL, !O_NONBLOCK) failed %E", 399*0Sigor@sysoev.ru fd, nxt_errno); 400*0Sigor@sysoev.ru return NXT_ERROR; 401*0Sigor@sysoev.ru } 402*0Sigor@sysoev.ru 403*0Sigor@sysoev.ru return NXT_OK; 404*0Sigor@sysoev.ru } 405*0Sigor@sysoev.ru 406*0Sigor@sysoev.ru #endif /* NXT_HAVE_FIONBIO */ 407*0Sigor@sysoev.ru 408*0Sigor@sysoev.ru 409*0Sigor@sysoev.ru ssize_t 410*0Sigor@sysoev.ru nxt_fd_write(nxt_fd_t fd, u_char *buf, size_t size) 411*0Sigor@sysoev.ru { 412*0Sigor@sysoev.ru ssize_t n; 413*0Sigor@sysoev.ru nxt_err_t err; 414*0Sigor@sysoev.ru 415*0Sigor@sysoev.ru n = write(fd, buf, size); 416*0Sigor@sysoev.ru 417*0Sigor@sysoev.ru err = (n == -1) ? nxt_errno : 0; 418*0Sigor@sysoev.ru 419*0Sigor@sysoev.ru nxt_thread_log_debug("write(%FD, %p, %uz): %z", fd, buf, size, n); 420*0Sigor@sysoev.ru 421*0Sigor@sysoev.ru if (nxt_slow_path(n <= 0)) { 422*0Sigor@sysoev.ru nxt_thread_log_alert("write(%FD) failed %E", fd, err); 423*0Sigor@sysoev.ru } 424*0Sigor@sysoev.ru 425*0Sigor@sysoev.ru return n; 426*0Sigor@sysoev.ru } 427*0Sigor@sysoev.ru 428*0Sigor@sysoev.ru 429*0Sigor@sysoev.ru ssize_t 430*0Sigor@sysoev.ru nxt_fd_read(nxt_fd_t fd, u_char *buf, size_t size) 431*0Sigor@sysoev.ru { 432*0Sigor@sysoev.ru ssize_t n; 433*0Sigor@sysoev.ru nxt_err_t err; 434*0Sigor@sysoev.ru 435*0Sigor@sysoev.ru n = read(fd, buf, size); 436*0Sigor@sysoev.ru 437*0Sigor@sysoev.ru err = (n == -1) ? nxt_errno : 0; 438*0Sigor@sysoev.ru 439*0Sigor@sysoev.ru nxt_thread_log_debug("read(%FD, %p, %uz): %z", fd, buf, size, n); 440*0Sigor@sysoev.ru 441*0Sigor@sysoev.ru if (nxt_slow_path(n <= 0)) { 442*0Sigor@sysoev.ru 443*0Sigor@sysoev.ru if (err == NXT_EAGAIN) { 444*0Sigor@sysoev.ru return 0; 445*0Sigor@sysoev.ru } 446*0Sigor@sysoev.ru 447*0Sigor@sysoev.ru nxt_thread_log_alert("read(%FD) failed %E", fd, err); 448*0Sigor@sysoev.ru } 449*0Sigor@sysoev.ru 450*0Sigor@sysoev.ru return n; 451*0Sigor@sysoev.ru } 452*0Sigor@sysoev.ru 453*0Sigor@sysoev.ru 454*0Sigor@sysoev.ru void 455*0Sigor@sysoev.ru nxt_fd_close(nxt_fd_t fd) 456*0Sigor@sysoev.ru { 457*0Sigor@sysoev.ru nxt_thread_log_debug("close(%FD)", fd); 458*0Sigor@sysoev.ru 459*0Sigor@sysoev.ru if (nxt_slow_path(close(fd) != 0)) { 460*0Sigor@sysoev.ru nxt_thread_log_error(NXT_LOG_CRIT, "close(%FD) failed %E", 461*0Sigor@sysoev.ru fd, nxt_errno); 462*0Sigor@sysoev.ru } 463*0Sigor@sysoev.ru } 464*0Sigor@sysoev.ru 465*0Sigor@sysoev.ru 466*0Sigor@sysoev.ru /* 467*0Sigor@sysoev.ru * nxt_file_redirect() redirects the file to the fd descriptor. 468*0Sigor@sysoev.ru * Then the fd descriptor is closed. 469*0Sigor@sysoev.ru */ 470*0Sigor@sysoev.ru 471*0Sigor@sysoev.ru nxt_int_t 472*0Sigor@sysoev.ru nxt_file_redirect(nxt_file_t *file, nxt_fd_t fd) 473*0Sigor@sysoev.ru { 474*0Sigor@sysoev.ru nxt_thread_log_debug("dup2(%FD, %FD, \"%FN\")", fd, file->fd, file->name); 475*0Sigor@sysoev.ru 476*0Sigor@sysoev.ru if (dup2(fd, file->fd) == -1) { 477*0Sigor@sysoev.ru nxt_thread_log_error(NXT_LOG_CRIT, "dup2(%FD, %FD, \"%FN\") failed %E", 478*0Sigor@sysoev.ru fd, file->fd, file->name, nxt_errno); 479*0Sigor@sysoev.ru return NXT_ERROR; 480*0Sigor@sysoev.ru } 481*0Sigor@sysoev.ru 482*0Sigor@sysoev.ru if (close(fd) != 0) { 483*0Sigor@sysoev.ru nxt_thread_log_error(NXT_LOG_CRIT, "close(%FD, \"%FN\") failed %E", 484*0Sigor@sysoev.ru fd, file->name, nxt_errno); 485*0Sigor@sysoev.ru return NXT_ERROR; 486*0Sigor@sysoev.ru } 487*0Sigor@sysoev.ru 488*0Sigor@sysoev.ru return NXT_OK; 489*0Sigor@sysoev.ru } 490*0Sigor@sysoev.ru 491*0Sigor@sysoev.ru 492*0Sigor@sysoev.ru /* nxt_file_stderr() redirects the stderr descriptor to the file. */ 493*0Sigor@sysoev.ru 494*0Sigor@sysoev.ru nxt_int_t 495*0Sigor@sysoev.ru nxt_file_stderr(nxt_file_t *file) 496*0Sigor@sysoev.ru { 497*0Sigor@sysoev.ru nxt_thread_log_debug("dup2(%FD, %FD, \"%FN\")", 498*0Sigor@sysoev.ru file->fd, STDERR_FILENO, file->name); 499*0Sigor@sysoev.ru 500*0Sigor@sysoev.ru if (dup2(file->fd, STDERR_FILENO) != -1) { 501*0Sigor@sysoev.ru return NXT_OK; 502*0Sigor@sysoev.ru } 503*0Sigor@sysoev.ru 504*0Sigor@sysoev.ru nxt_thread_log_error(NXT_LOG_CRIT, "dup2(%FD, %FD, \"%FN\") failed %E", 505*0Sigor@sysoev.ru file->fd, STDERR_FILENO, file->name); 506*0Sigor@sysoev.ru 507*0Sigor@sysoev.ru return NXT_ERROR; 508*0Sigor@sysoev.ru } 509*0Sigor@sysoev.ru 510*0Sigor@sysoev.ru 511*0Sigor@sysoev.ru nxt_int_t 512*0Sigor@sysoev.ru nxt_stderr_start(void) 513*0Sigor@sysoev.ru { 514*0Sigor@sysoev.ru int flags, fd; 515*0Sigor@sysoev.ru 516*0Sigor@sysoev.ru flags = fcntl(nxt_stderr, F_GETFL); 517*0Sigor@sysoev.ru 518*0Sigor@sysoev.ru if (flags != -1) { 519*0Sigor@sysoev.ru /* 520*0Sigor@sysoev.ru * If the stderr output of a multithreaded application is 521*0Sigor@sysoev.ru * redirected to a file: 522*0Sigor@sysoev.ru * Linux, Solaris and MacOSX do not write atomically to the output; 523*0Sigor@sysoev.ru * MacOSX besides adds zeroes to the output. 524*0Sigor@sysoev.ru * O_APPEND fixes this. 525*0Sigor@sysoev.ru */ 526*0Sigor@sysoev.ru (void) fcntl(nxt_stderr, F_SETFL, flags | O_APPEND); 527*0Sigor@sysoev.ru 528*0Sigor@sysoev.ru } else { 529*0Sigor@sysoev.ru /* 530*0Sigor@sysoev.ru * The stderr descriptor is closed before application start. 531*0Sigor@sysoev.ru * Reserve the stderr descriptor for future use. Errors are 532*0Sigor@sysoev.ru * ignored because anyway they could be written nowhere. 533*0Sigor@sysoev.ru */ 534*0Sigor@sysoev.ru fd = open("/dev/null", O_WRONLY | O_APPEND); 535*0Sigor@sysoev.ru 536*0Sigor@sysoev.ru if (fd != -1) { 537*0Sigor@sysoev.ru (void) dup2(fd, nxt_stderr); 538*0Sigor@sysoev.ru 539*0Sigor@sysoev.ru if (fd != nxt_stderr) { 540*0Sigor@sysoev.ru (void) close(fd); 541*0Sigor@sysoev.ru } 542*0Sigor@sysoev.ru } 543*0Sigor@sysoev.ru } 544*0Sigor@sysoev.ru 545*0Sigor@sysoev.ru return flags; 546*0Sigor@sysoev.ru } 547*0Sigor@sysoev.ru 548*0Sigor@sysoev.ru 549*0Sigor@sysoev.ru nxt_int_t 550*0Sigor@sysoev.ru nxt_pipe_create(nxt_fd_t *pp, nxt_bool_t nbread, nxt_bool_t nbwrite) 551*0Sigor@sysoev.ru { 552*0Sigor@sysoev.ru if (pipe(pp) != 0) { 553*0Sigor@sysoev.ru nxt_thread_log_alert("pipe() failed %E", nxt_errno); 554*0Sigor@sysoev.ru 555*0Sigor@sysoev.ru return NXT_ERROR; 556*0Sigor@sysoev.ru } 557*0Sigor@sysoev.ru 558*0Sigor@sysoev.ru nxt_thread_log_debug("pipe(): %FD:%FD", pp[0], pp[1]); 559*0Sigor@sysoev.ru 560*0Sigor@sysoev.ru if (nbread) { 561*0Sigor@sysoev.ru if (nxt_fd_nonblocking(pp[0]) != NXT_OK) { 562*0Sigor@sysoev.ru return NXT_ERROR; 563*0Sigor@sysoev.ru } 564*0Sigor@sysoev.ru } 565*0Sigor@sysoev.ru 566*0Sigor@sysoev.ru if (nbwrite) { 567*0Sigor@sysoev.ru if (nxt_fd_nonblocking(pp[1]) != NXT_OK) { 568*0Sigor@sysoev.ru return NXT_ERROR; 569*0Sigor@sysoev.ru } 570*0Sigor@sysoev.ru } 571*0Sigor@sysoev.ru 572*0Sigor@sysoev.ru return NXT_OK; 573*0Sigor@sysoev.ru } 574*0Sigor@sysoev.ru 575*0Sigor@sysoev.ru 576*0Sigor@sysoev.ru void 577*0Sigor@sysoev.ru nxt_pipe_close(nxt_fd_t *pp) 578*0Sigor@sysoev.ru { 579*0Sigor@sysoev.ru nxt_thread_log_debug("pipe close(%FD:%FD)", pp[0], pp[1]); 580*0Sigor@sysoev.ru 581*0Sigor@sysoev.ru if (close(pp[0]) != 0) { 582*0Sigor@sysoev.ru nxt_thread_log_alert("pipe close (%FD) failed %E", pp[0], nxt_errno); 583*0Sigor@sysoev.ru } 584*0Sigor@sysoev.ru 585*0Sigor@sysoev.ru if (close(pp[1]) != 0) { 586*0Sigor@sysoev.ru nxt_thread_log_alert("pipe close(%FD) failed %E", pp[1], nxt_errno); 587*0Sigor@sysoev.ru } 588*0Sigor@sysoev.ru } 589*0Sigor@sysoev.ru 590*0Sigor@sysoev.ru 591*0Sigor@sysoev.ru size_t 592*0Sigor@sysoev.ru nxt_dir_current(char *buf, size_t len) 593*0Sigor@sysoev.ru { 594*0Sigor@sysoev.ru if (nxt_fast_path(getcwd(buf, len) != NULL)) { 595*0Sigor@sysoev.ru return nxt_strlen(buf); 596*0Sigor@sysoev.ru } 597*0Sigor@sysoev.ru 598*0Sigor@sysoev.ru nxt_thread_log_alert("getcwd(%uz) failed %E", len, nxt_errno); 599*0Sigor@sysoev.ru 600*0Sigor@sysoev.ru return 0; 601*0Sigor@sysoev.ru } 602