static void sfree_pool(struct pool *pool, void *ptr) { struct block_hdr *hdr; unsigned int i, idx; unsigned long offset; if (!ptr) return; ptr -= sizeof(*hdr); hdr = ptr; assert(ptr_valid(pool, ptr)); sfree_check_redzone(hdr); offset = ptr - pool->map; i = offset / SMALLOC_BPL; idx = (offset % SMALLOC_BPL) / SMALLOC_BPB; fio_mutex_down(pool->lock); clear_blocks(pool, i, idx, size_to_blocks(hdr->size)); if (i < pool->next_non_full) pool->next_non_full = i; pool->free_blocks += size_to_blocks(hdr->size); fio_mutex_up(pool->lock); }
int mingw_fstat(int fd, struct mingw_stat *buf) { HANDLE fh = (HANDLE)_get_osfhandle(fd); BY_HANDLE_FILE_INFORMATION fdata; if (fh == INVALID_HANDLE_VALUE) { errno = EBADF; return -1; } /* direct non-file handles to MS's fstat() */ if (GetFileType(fh) != FILE_TYPE_DISK) { struct stat st; if (fstat(fd, &st)) return -1; buf->st_ino = st.st_ino; buf->st_gid = st.st_gid; buf->st_uid = st.st_uid; buf->st_mode = st.st_mode; buf->st_size = st.st_size; buf->st_blocks = size_to_blocks(buf->st_size); buf->st_dev = st.st_dev; buf->st_atime = st.st_atime; buf->st_mtime = st.st_mtime; buf->st_ctime = st.st_ctime; return 0; } if (GetFileInformationByHandle(fh, &fdata)) { int fMode = S_IREAD; if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) fMode |= S_IFDIR; else fMode |= S_IFREG; if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) fMode |= S_IWRITE; buf->st_ino = 0; buf->st_gid = 0; buf->st_uid = 0; buf->st_mode = fMode; buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */ buf->st_blocks = size_to_blocks(buf->st_size); buf->st_dev = _getdrive() - 1; buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime)); buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime)); buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime)); return 0; } errno = EBADF; return -1; }
static void *__smalloc_pool(struct pool *pool, size_t size) { size_t nr_blocks; unsigned int i; unsigned int offset; unsigned int last_idx; void *ret = NULL; fio_mutex_down(pool->lock); nr_blocks = size_to_blocks(size); if (nr_blocks > pool->free_blocks) goto fail; i = pool->next_non_full; last_idx = 0; offset = -1U; while (i < pool->nr_blocks) { unsigned int idx; if (pool->bitmap[i] == -1U) { i++; pool->next_non_full = i; last_idx = 0; continue; } idx = find_next_zero(pool->bitmap[i], last_idx); if (!blocks_free(pool, i, idx, nr_blocks)) { idx += nr_blocks; if (idx < SMALLOC_BPI) last_idx = idx; else { last_idx = 0; while (idx >= SMALLOC_BPI) { i++; idx -= SMALLOC_BPI; } } continue; } set_blocks(pool, i, idx, nr_blocks); offset = i * SMALLOC_BPL + idx * SMALLOC_BPB; break; } if (i < pool->nr_blocks) { pool->free_blocks -= nr_blocks; ret = pool->map + offset; } fail: fio_mutex_up(pool->lock); return ret; }
/* do_stat is a common implementation for cygwin_lstat and cygwin_stat. * * To simplify its logic, in the case of cygwin symlinks, this implementation * falls back to the cygwin version of stat/lstat, which is provided as the * last argument. */ static int do_stat(const char *file_name, struct stat *buf, stat_fn_t cygstat) { WIN32_FILE_ATTRIBUTE_DATA fdata; if (file_name[0] == '/') return cygstat (file_name, buf); if (!(errno = get_file_attr(file_name, &fdata))) { /* * If the system attribute is set and it is not a directory then * it could be a symbol link created in the nowinsymlinks mode. * Normally, Cygwin works in the winsymlinks mode, so this situation * is very unlikely. For the sake of simplicity of our code, let's * Cygwin to handle it. */ if ((fdata.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) && !(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) return cygstat(file_name, buf); /* fill out the stat structure */ buf->st_dev = buf->st_rdev = 0; /* not used by Git */ buf->st_ino = 0; buf->st_mode = file_attr_to_st_mode(fdata.dwFileAttributes); buf->st_nlink = 1; buf->st_uid = buf->st_gid = 0; #ifdef __CYGWIN_USE_BIG_TYPES__ buf->st_size = ((_off64_t)fdata.nFileSizeHigh << 32) + fdata.nFileSizeLow; #else buf->st_size = (off_t)fdata.nFileSizeLow; #endif buf->st_blocks = size_to_blocks(buf->st_size); filetime_to_timespec(&fdata.ftLastAccessTime, &buf->st_atim); filetime_to_timespec(&fdata.ftLastWriteTime, &buf->st_mtim); filetime_to_timespec(&fdata.ftCreationTime, &buf->st_ctim); return 0; } else if (errno == ENOENT) { /* * In the winsymlinks mode (which is the default), Cygwin * emulates symbol links using Windows shortcut files. These * files are formed by adding .lnk extension. So, if we have * not found the specified file name, it could be that it is * a symbol link. Let's Cygwin to deal with that. */ return cygstat(file_name, buf); } return -1; }
/* We keep the do_lstat code in a separate function to avoid recursion. * When a path ends with a slash, the stat will fail with ENOENT. In * this case, we strip the trailing slashes and stat again. */ static int do_lstat(const char *file_name, struct stat *buf) { WIN32_FILE_ATTRIBUTE_DATA fdata; if (GetFileAttributesExA(file_name, GetFileExInfoStandard, &fdata)) { int fMode = S_IREAD; if (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) fMode |= S_IFDIR; else fMode |= S_IFREG; if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_READONLY)) fMode |= S_IWRITE; buf->st_ino = 0; buf->st_gid = 0; buf->st_uid = 0; buf->st_mode = fMode; buf->st_size = fdata.nFileSizeLow; /* Can't use nFileSizeHigh, since it's not a stat64 */ buf->st_blocks = size_to_blocks(buf->st_size); buf->st_dev = _getdrive() - 1; buf->st_atime = filetime_to_time_t(&(fdata.ftLastAccessTime)); buf->st_mtime = filetime_to_time_t(&(fdata.ftLastWriteTime)); buf->st_ctime = filetime_to_time_t(&(fdata.ftCreationTime)); errno = 0; return 0; } switch (GetLastError()) { case ERROR_ACCESS_DENIED: case ERROR_SHARING_VIOLATION: case ERROR_LOCK_VIOLATION: case ERROR_SHARING_BUFFER_EXCEEDED: errno = EACCES; break; case ERROR_BUFFER_OVERFLOW: errno = ENAMETOOLONG; break; case ERROR_NOT_ENOUGH_MEMORY: errno = ENOMEM; break; default: errno = ENOENT; break; } return -1; }