57#if CONFIG_TARFS_HAVE_SENDFILE
58# include <sys/socket.h>
82#define PROLOGUE( TYPE ) \
83 struct tarfs_fs *fs = NULL; \
85 int fs_idx = (intptr_t )ctx; \
87 if (false == (fs_idx >= 0 && \
88 fs_idx < TARFS_MAX_FS && \
89 ((fs = tarfs_getfs(fs_idx)) != NULL))) { \
91 log("FS#%d is not mounted\r\n",fs_idx); \
95 if (!is_sanefd(fs, fd)) { \
96 log("FS#%d, fd#%d is not open\r\n", fs_idx, fd); \
103#if CONFIG_TARFS_COUNTERS
104# define ADD_STATS(X, Y) do { X += Y; } while(0)
106# define ADD_STATS(X, Y) do {} while(0)
133 uint32_t used_indices, new_value;
136 used_indices = atomic_load_explicit(&fs->fs_usedfd, memory_order_relaxed);
142 index = __builtin_ctz(free_mask);
143 new_value = used_indices | (1u << index);
145 }
while (!atomic_compare_exchange_weak_explicit(
149 memory_order_relaxed,
150 memory_order_relaxed));
160 uint32_t used_indices, new_value;
166 used_indices = atomic_load_explicit(&fs->fs_usedfd, memory_order_relaxed);
167 new_value = used_indices & ~(1u << index);
169 }
while (!atomic_compare_exchange_weak_explicit(
173 memory_order_relaxed,
174 memory_order_relaxed));
186 ((atomic_load_explicit(&fs->fs_usedfd, memory_order_relaxed) & (1u << fd)) != 0);
214 else if (amode & W_OK)
222 if (S_ISREG(st.st_mode)) {
225 if ((amode & (F_OK|R_OK)) || amode == F_OK)
228 }
else if (S_ISDIR(st.st_mode)) {
236 if ((amode & F_OK) || (amode == F_OK))
258 const char *path = path0;
259 char *alt_path = NULL;
264 int const fs_idx = (int )(intptr_t )ctx;
272 if (((flags & O_ACCMODE) == O_WRONLY) || (flags & O_TRUNC)) {
287 log(
"bad filesystem context: %d, %p\r\n",fs_idx, (
void *)fs);
305 if (flags & O_DIRECTORY) {
307 int i = strlen(path);
324 if (path[i - 1] !=
'/') {
328 if (alt_path != NULL)
337 if (alt_path != NULL)
338 alt_path[i - 1] =
'\0';
344 if (alt_path != NULL) {
345 log(
"trying '%s' instead..\r\n",alt_path);
354 log(
"path '%s' not found\r\n",path);
364 struct tarfs_inode const *inode = fs->
fs_ino[idx];
365 if (inode->in_dvaddr == 0) {
367 log(
"floating inode '%s', no data\r\n", path);
379 if ((flags & O_DIRECTORY) != 0) {
380 if (
type != TART_DIR) {
381 log(
"O_DIRECTORY specified for a non-directory object\r\n");
391 if (
type == TART_DIR) {
392 log(
"target is a directory, O_DIRECTORY flag is required\r\n");
399#if CONFIG_TARFS_INTEGRITY
402 log(
"data integrity check failed for '%s'\r\n", path);
417 log(
"fd=%d allocated\r\n", fd);
425 log(
"success, ino=%d, type=%c, path=%s, fd=%d, size=%u, vaddr=%p\r\n",idx,
type, path, fd,(
unsigned int)fp->
fp_size, (
void *)fp->
fp_vaddr);
430 log(
"allocfd failed for path=%s\r\n",path);
450 log(
"closing fd=%d, fs_idx=%d\r\n", fd, fs_idx);
469 struct tarfs_fp *fp = &fs->fs_fd[fd];
476 size_t off = (size_t)offset;
488 void const *src = (
void const *)(fp->
fp_vaddr + off);
517 struct tarfs_fp *fp = &fs->fs_fd[fd];
522 fp->
fp_pos += (size_t)siz;
533off_t
tarf_lseek(
void* ctx,
int fd, off_t offset,
int whence) {
546 if (whence == SEEK_SET) {
548 if (offset >= 0 && offset <= fp->
fp_size) {
553 }
else if (whence == SEEK_END) {
563 uint64_t back = (uint64_t)(-(offset + 1)) + 1;
570 }
else if (whence == SEEK_CUR) {
572 off_t new_offset = offset + (off_t)fp->
fp_pos;
573 if (new_offset >= 0 && new_offset <= fp->
fp_size) {
579 log(
"bad whence(%d) or/and offset(%ld)\r\n", whence, offset);
596 struct tarfs_fp *fp = &fs->fs_fd[fd];
600 memset(st, 0,
sizeof(
struct stat));
602 uint32_t perm = S_IRUSR|S_IRGRP|S_IROTH;
604 if (
type == TART_DIR)
605 perm |= S_IXUSR|S_IXGRP|S_IXOTH|S_IFDIR;
609 st->st_dev = (dev_t)fs_idx;
610 st->st_ino = (ino_t)fp->
fp_idx;
611 st->st_blksize = 512;
612 st->st_blocks = ((fp->
fp_size + 511) & ~511) / 512;
615 st->st_mtime = fs->fs_mtime;
617 st->st_ctime = fs->fs_mtime;
622#if CONFIG_TARFS_HAVE_LSTAT
627int tarf_lstat(
void* ctx,
const char *path,
struct stat * st) {
632 struct tarfs_inode const *ino;
634 int fd, fs_idx = (int)(intptr_t )ctx;
640 if ((fd =
tarf_open(ctx, path, 0, 0)) < 0) {
641 if ((fd =
tarf_open(ctx, path, O_DIRECTORY, 0)) < 0) {
642 log(
"path not found: %s\r\n", path);
652 log(
"bad filesystem context: %d\r\n",fs_idx);
668 memset(st, 0,
sizeof(
struct stat));
670 perm = S_IRUSR|S_IRGRP|S_IROTH;
673 if (
type == TART_DIR) {
674 perm |= S_IXUSR|S_IXGRP|S_IXOTH|S_IFDIR;
676 }
else if (
type == TART_HARDLINK ||
type == TART_SYMLINK) {
683 st->st_dev = (dev_t)fs_idx;
684 st->st_ino = (ino_t)in_idx;
685 st->st_blksize = 512;
686 st->st_blocks = ((
size + 511) & ~511) / 512;
725 return O_NONBLOCK | O_RDONLY;
751 o = va_arg(args,
int *);
790int tarf_stat(
void* ctx,
const char * path,
struct stat * st) {
795 if ((
fd =
tarf_open(ctx, path, O_RDONLY, 0)) < 0) {
796 if ((
fd =
tarf_open(ctx, path, O_RDONLY | O_DIRECTORY, 0)) < 0) {
797 log(
"path does not exist (not file not directory)");
828 log(
"fd=%d was duplicated as fd=%d\r\n",
fd, dup);
833 log(
"fd=%d NOT duplicated, EMFILE!\r\n",
fd);
846void *
tarf_mmap(
void *ctx,
void *addr,
size_t length,
int prot,
int flags,
int fd, off_t offset) {
854 if (((flags &
MAP_FIXED) && addr != NULL) ||
858 log(
"Unsupported combination of flags/protection\r\n");
869 length > (fp->
fp_size - offset)) {
871 log(
"failed: offset=%u, fp_size=%u, length=%u\r\n", (
unsigned int)offset, (
unsigned int)fp->
fp_size, (
unsigned int)length);
880 log(
"fd=%d, mapped %u bytes vaddr=%p, offset=%d\r\n",fd, (
unsigned int)length, (
void *)fp->
fp_vaddr, (
int)offset);
885 return (
void *)(fp->
fp_vaddr + offset);
902 int fs_idx = (intptr_t )ctx;
904 if (
false == (fs_idx >= 0 &&
908 log(
"filesystem #%d is not mounted\r\n",fs_idx);
913 log(
"unmapping ptr=%p (len=%u) from fs_idx=%d\r\n",(
void *)addr, (
unsigned int)length, fs_idx);
919#if CONFIG_TARFS_HAVE_SENDFILE
926ssize_t
tarf_sendfile(
void *ctx,
int sock,
int fd, off_t *offset,
size_t count) {
946 log(
"bad virtual address, fd=%d\r\n", fd);
953 if (offset != NULL ) {
958 if (pos < 0 || pos > fp->
fp_size) {
959 log(
"bad user-supplied pos=%d\r\n",(
int)pos);
968 if (count > (fp->
fp_size - pos))
972 data = (
void *)(fp->
fp_vaddr + pos);
977 while (total < count) {
979 ssize_t n = send(sock, data + total, count - total, 0);
985 log(
"send failed\r\n");
994 log(
"sent %u\r\n", (
unsigned int)n);
int tarf_stat(void *ctx, const char *path, struct stat *st)
stat() system call
static bool is_sanefd(struct tarfs_fs *fs, int fd)
Extra paranoia: we check fds which are passed to us by VFS layer for being in our range [0 .
off_t tarf_lseek(void *ctx, int fd, off_t offset, int whence)
lseek()
ssize_t tarf_sendfile(void *ctx, int sock, int fd, off_t *offset, size_t count)
Copy data from a TARFS file descriptor to a socket.
int tarf_close(void *ctx, int fd)
int tarf_access(void *ctx, const char *path, int amode)
Check the accessibility of a file or directory in the TarFS filesystem.
int tarf_fstat(void *ctx, int fd, struct stat *st)
Get file status information.
ssize_t tarf_pread(void *ctx, int fd, void *dst, size_t size, off_t offset)
Read data from an open TARFS file at a specified offset.
int tarf_ioctl(void *ctx, int fd, int cmd, va_list args)
Perform TARFS-specific I/O control operations.
ssize_t tarf_read(void *ctx, int fd, void *dst, size_t size)
Read data from an open TARFS file.
void * tarf_mmap(void *ctx, void *addr, size_t length, int prot, int flags, int fd, off_t offset)
Mimics POSIX mmap().
int tarf_dupfd(void *ctx, int fd)
Create an independent duplicate of a file descriptor.
int tarf_fcntl(void *ctx, int fd, int cmd, int arg)
Perform file descriptor control operations.
int tarf_munmap(void *ctx, void *addr, size_t length)
munmap().
static void freefd(struct tarfs_fs *fs, int index)
Marks previously allocated index as free.
int tarf_open(void *ctx, const char *path0, int flags, int mode)
Open a TARFS file or directory.
int tarf_fsync(void *ctx, int fd)
Synchronize file contents.
static const uint32_t s_valid_mask
static int allocfd(struct tarfs_fs *fs)
Allocate a file descriptor slot.
int tarfs_unref(struct tarfs_fs *fs)
struct tarfs_fs * tarfs_getfs(int i)
Lockless, not thread safe, does not increase refcounters.
int tarfs_addref(struct tarfs_fs *fs)
Filesystem reference counting.
struct tarfs_fs * tarfs_getfs_addref(int i)
Thread safe, increases refcounter, uses mutex!
tart_t inode_getinfo(struct tarfs_inode const *const *index, int idx, size_t *size, time_t *mtime)
inode_getinfo() : get inode's Type, Size and Mtime These are not precached and must be calculated eve...
tart_t inode_rawtype(struct tarfs_inode const *ino)
Return raw inode type: TART_HARDLINK, TART_SYMLINK, TART_DIR, TART_FILE or TART_BAD.
int inode_lookup(struct tarfs_inode const *const *index, size_t num_inodes, const char *path)
Find an inode that corresponds to given path name.
static void * tarfs_os_memcpy(void *dst, const void *src, size_t len)
read() uses memcpy(), which can be optimized on many architectures
void tarfs_os_free(void *buffer)
Return/Request argument for FIOGETFD ioctl.
TARFS File API: tarf_open(), tarf_close(), tarf_read(), tarf_pread(), tarf_lseek(),...
This descriptor holds all file descriptors opened.
struct tarfs_fp fs_fd[16]
tarfs_inode_t const *const * fs_ino
For TAR files with modified PADDING field (see tarsum.c TARFS Checksum Utility): The type and meaning...
char * tar_strdup1(const char *s1, const char *s1_end)
Duplicate a TAR string as a regular NUL-terminated C string.
bool tar_baddata(struct tarhdr const *hdr, size_t size)
Verify CRC64 checksum stored in a TAR archive, if present.