static int setutent_file (void) { if (file_fd < 0) { const char *file_name; file_name = TRANSFORM_UTMP_FILE_NAME (__libc_utmp_file_name); file_writable = false; file_fd = __open_nocancel (file_name, O_RDONLY | O_LARGEFILE | O_CLOEXEC); if (file_fd == -1) return 0; } __lseek64 (file_fd, 0, SEEK_SET); file_offset = 0; /* Make sure the entry won't match. */ #if _HAVE_UT_TYPE - 0 last_entry.ut_type = -1; #else last_entry.ut_line[0] = '\177'; # if _HAVE_UT_ID - 0 last_entry.ut_id[0] = '\0'; # endif #endif return 1; }
off_t __lseek (int fd, off_t offset, int whence) { off64_t res = __lseek64 (fd, offset, whence); if (res != (off_t) res) { __set_errno (EOVERFLOW); return (off_t) -1; } return (off_t) res; }
static int _IO_file_sync_mmap (_IO_FILE *fp) { if (fp->_IO_read_ptr != fp->_IO_read_end) { #ifdef TODO if (_IO_in_backup (fp)) delta -= eGptr () - Gbase (); #endif if (__lseek64 (fp->_fileno, fp->_IO_read_ptr - fp->_IO_buf_base, SEEK_SET) != fp->_IO_read_ptr - fp->_IO_buf_base) { fp->_flags |= _IO_ERR_SEEN; return EOF; } } fp->_offset = fp->_IO_read_ptr - fp->_IO_buf_base; fp->_IO_read_end = fp->_IO_read_ptr = fp->_IO_read_base; return 0; }
static void decide_maybe_mmap (_IO_FILE *fp) { /* We use the file in read-only mode. This could mean we can mmap the file and use it without any copying. But not all file descriptors are for mmap-able objects and on 32-bit machines we don't want to map files which are too large since this would require too much virtual memory. */ struct stat64 st; if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode) && st.st_size != 0 /* Limit the file size to 1MB for 32-bit machines. */ && (sizeof (ptrdiff_t) > 4 || st.st_size < 1*1024*1024) /* Sanity check. */ && (fp->_offset == _IO_pos_BAD || fp->_offset <= st.st_size)) { /* Try to map the file. */ void *p; p = __mmap64 (NULL, st.st_size, PROT_READ, MAP_SHARED, fp->_fileno, 0); if (p != MAP_FAILED) { /* OK, we managed to map the file. Set the buffer up and use a special jump table with simplified underflow functions which never tries to read anything from the file. */ if (__lseek64 (fp->_fileno, st.st_size, SEEK_SET) != st.st_size) { (void) __munmap (p, st.st_size); fp->_offset = _IO_pos_BAD; } else { _IO_setb (fp, p, (char *) p + st.st_size, 0); if (fp->_offset == _IO_pos_BAD) fp->_offset = 0; _IO_setg (fp, p, p + fp->_offset, p + st.st_size); fp->_offset = st.st_size; if (fp->_mode <= 0) _IO_JUMPS_FILE_plus (fp) = &_IO_file_jumps_mmap; else _IO_JUMPS_FILE_plus (fp) = &_IO_wfile_jumps_mmap; fp->_wide_data->_wide_vtable = &_IO_wfile_jumps_mmap; return; } } } /* We couldn't use mmap, so revert to the vanilla file operations. */ if (fp->_mode <= 0) _IO_JUMPS_FILE_plus (fp) = &_IO_file_jumps; else _IO_JUMPS_FILE_plus (fp) = &_IO_wfile_jumps; fp->_wide_data->_wide_vtable = &_IO_wfile_jumps; }
/* Guts of underflow callback if we mmap the file. This stats the file and updates the stream state to match. In the normal case we return zero. If the file is no longer eligible for mmap, its jump tables are reset to the vanilla ones and we return nonzero. */ static int mmap_remap_check (_IO_FILE *fp) { struct stat64 st; if (_IO_SYSSTAT (fp, &st) == 0 && S_ISREG (st.st_mode) && st.st_size != 0 /* Limit the file size to 1MB for 32-bit machines. */ && (sizeof (ptrdiff_t) > 4 || st.st_size < 1*1024*1024)) { const size_t pagesize = __getpagesize (); # define ROUNDED(x) (((x) + pagesize - 1) & ~(pagesize - 1)) if (ROUNDED (st.st_size) < ROUNDED (fp->_IO_buf_end - fp->_IO_buf_base)) { /* We can trim off some pages past the end of the file. */ (void) __munmap (fp->_IO_buf_base + ROUNDED (st.st_size), ROUNDED (fp->_IO_buf_end - fp->_IO_buf_base) - ROUNDED (st.st_size)); fp->_IO_buf_end = fp->_IO_buf_base + st.st_size; } else if (ROUNDED (st.st_size) > ROUNDED (fp->_IO_buf_end - fp->_IO_buf_base)) { /* The file added some pages. We need to remap it. */ void *p; #ifdef _G_HAVE_MREMAP p = __mremap (fp->_IO_buf_base, ROUNDED (fp->_IO_buf_end - fp->_IO_buf_base), ROUNDED (st.st_size), MREMAP_MAYMOVE); if (p == MAP_FAILED) { (void) __munmap (fp->_IO_buf_base, fp->_IO_buf_end - fp->_IO_buf_base); goto punt; } #else (void) __munmap (fp->_IO_buf_base, fp->_IO_buf_end - fp->_IO_buf_base); p = __mmap64 (NULL, st.st_size, PROT_READ, MAP_SHARED, fp->_fileno, 0); if (p == MAP_FAILED) goto punt; #endif fp->_IO_buf_base = p; fp->_IO_buf_end = fp->_IO_buf_base + st.st_size; } else { /* The number of pages didn't change. */ fp->_IO_buf_end = fp->_IO_buf_base + st.st_size; } # undef ROUNDED fp->_offset -= fp->_IO_read_end - fp->_IO_read_ptr; _IO_setg (fp, fp->_IO_buf_base, fp->_offset < fp->_IO_buf_end - fp->_IO_buf_base ? fp->_IO_buf_base + fp->_offset : fp->_IO_buf_end, fp->_IO_buf_end); /* If we are already positioned at or past the end of the file, don't change the current offset. If not, seek past what we have mapped, mimicking the position left by a normal underflow reading into its buffer until EOF. */ if (fp->_offset < fp->_IO_buf_end - fp->_IO_buf_base) { if (__lseek64 (fp->_fileno, fp->_IO_buf_end - fp->_IO_buf_base, SEEK_SET) != fp->_IO_buf_end - fp->_IO_buf_base) fp->_flags |= _IO_ERR_SEEN; else fp->_offset = fp->_IO_buf_end - fp->_IO_buf_base; } return 0; } else { /* Life is no longer good for mmap. Punt it. */ (void) __munmap (fp->_IO_buf_base, fp->_IO_buf_end - fp->_IO_buf_base); punt: fp->_IO_buf_base = fp->_IO_buf_end = NULL; _IO_setg (fp, NULL, NULL, NULL); if (fp->_mode <= 0) _IO_JUMPS_FILE_plus (fp) = &_IO_file_jumps; else _IO_JUMPS_FILE_plus (fp) = &_IO_wfile_jumps; fp->_wide_data->_wide_vtable = &_IO_wfile_jumps; return 1; } }
_IO_off64_t _IO_file_seek (_IO_FILE *fp, _IO_off64_t offset, int dir) { return __lseek64 (fp->_fileno, offset, dir); }
static int setutent_file (void) { if (file_fd < 0) { const char *file_name; file_name = TRANSFORM_UTMP_FILE_NAME (__libc_utmp_file_name); #ifdef O_CLOEXEC # define O_flags O_LARGEFILE | O_CLOEXEC #else # define O_flags O_LARGEFILE #endif file_writable = false; file_fd = open_not_cancel_2 (file_name, O_RDONLY | O_flags); if (file_fd == -1) return 0; #ifndef __ASSUME_O_CLOEXEC # ifdef O_CLOEXEC if (__have_o_cloexec <= 0) # endif { /* We have to make sure the file is `closed on exec'. */ int result = fcntl_not_cancel (file_fd, F_GETFD, 0); if (result >= 0) { # ifdef O_CLOEXEC if (__have_o_cloexec == 0) __have_o_cloexec = (result & FD_CLOEXEC) ? 1 : -1; if (__have_o_cloexec < 0) # endif result = fcntl_not_cancel (file_fd, F_SETFD, result | FD_CLOEXEC); } if (result == -1) { close_not_cancel_no_status (file_fd); return 0; } } #endif } __lseek64 (file_fd, 0, SEEK_SET); file_offset = 0; /* Make sure the entry won't match. */ #if _HAVE_UT_TYPE - 0 last_entry.ut_type = -1; #else last_entry.ut_line[0] = '\177'; # if _HAVE_UT_ID - 0 last_entry.ut_id[0] = '\0'; # endif #endif return 1; }