1#include <clod/stream.h>
17#define O_DIRECTORY 0200000
35 switch (flags & (CLOD_FILE_READ | CLOD_FILE_WRITE | CLOD_FILE_TRUNCATE | CLOD_FILE_DIRECTORY)) {
37 o_flags |= O_RDONLY;
break;
38 case CLOD_FILE_READ | CLOD_FILE_DIRECTORY:
39 o_flags |= O_RDONLY | O_DIRECTORY;
break;
40 case CLOD_FILE_READ | CLOD_FILE_WRITE:
41 o_flags |= O_RDWR;
break;
42 case CLOD_FILE_READ | CLOD_FILE_WRITE | CLOD_FILE_TRUNCATE:
43 o_flags |= O_RDWR | O_TRUNC;
break;
45 o_flags |= O_WRONLY;
break;
46 case CLOD_FILE_WRITE | CLOD_FILE_TRUNCATE:
47 o_flags |= O_WRONLY | O_TRUNC;
break;
48 case CLOD_FILE_DIRECTORY:
49 o_flags |= O_DIRECTORY;
break;
52 return CLOD_STREAM_INVALID;
55 if (flags & CLOD_FILE_CREATE) {
59 if (flags & CLOD_FILE_APPEND) {
65 res = syscall(__NR_openat, (
int)(
long)directory->
impl, (
long)path, o_flags, 0664);
67 res = syscall(__NR_open, (
long)path, o_flags, 0664);
69 if (res == -EINVAL || res == -EFAULT || res == -EBADF)
return CLOD_STREAM_INVALID;
70 if (res == -ENOENT)
return CLOD_STREAM_EOF;
71 if (res < 0)
return (
int)-res;
73 stream_out->
impl = (uintptr_t)res;
75 if (flags & CLOD_FILE_READ) {
76 if (flags & CLOD_FILE_DIRECTORY) {
77 stream_out->
read = clod_file_stream_readdir;
79 stream_out->
read = clod_file_stream_read;
82 stream_out->
read =
nullptr;
85 if (flags & CLOD_FILE_WRITE) {
86 stream_out->
write = clod_file_stream_write;
88 stream_out->
write =
nullptr;
91 stream_out->
close = clod_file_stream_close;
93 return CLOD_STREAM_OK;
98 return CLOD_STREAM_OK;
100 const long ret = syscall(__NR_read, (
long)self->
impl, (
long)(dst->
ptr + dst->
len), dst->
cap - dst->
len);
101 if (ret < 0)
return (
int)-ret;
103 return CLOD_STREAM_EOF;
106 return CLOD_STREAM_OK;
110 return CLOD_STREAM_OK;
112 long res = syscall(__NR_getdents64, (
long)self->
impl, (
long)(dst->
ptr + dst->
len), dst->
cap - dst->
len);
113 if (res == 0)
return CLOD_STREAM_EOF;
114 if (res == -EBADF)
return CLOD_STREAM_INVALID;
115 if (res < 0)
return (
int)-res;
118 while (off < (
size_t)res) {
119 void *ptr = dst->
ptr + dst->
len + off;
125 clod_ent->
next = off < (size_t)res ? (
struct clod_dirent*)((
char*)ptr + ent.size) :
nullptr;
126 clod_ent->
id = (uintptr_t)ent.ino;
127 clod_ent->name_size = ent.size - (
unsigned short)offsetof(
struct linux_dirent,
name) - 1;
129 case DT_DIR: clod_ent->type = CLOD_DIRENT_DIRECTORY;
break;
130 case DT_REG: clod_ent->type = CLOD_DIRENT_FILE;
break;
131 default: clod_ent->type = ent.type;
134 return CLOD_STREAM_OK;
138 return CLOD_STREAM_OK;
141 const long ret = syscall(__NR_write, (
long)self->
impl, (
long)src->
ptr, src->
len);
146 if (src->
cap) src->
cap -= ret;
149 if (ret < 0)
return (
int)-ret;
152 return CLOD_STREAM_OK;
156 const long ret = syscall(__NR_close, (
long)self->
impl);
157 if (ret < 0)
return (
int)-ret;
158 return CLOD_STREAM_OK;
163 .read = clod_file_stream_read,
164 .close = clod_file_stream_close,
169 .write = clod_file_stream_write,
170 .close = clod_file_stream_close
175 .write = clod_file_stream_write,
176 .close = clod_file_stream_close,
struct clod_dirent * next
Pointer to the next directory entry.
char name[]
Name of the entry.
uintptr_t id
Unique identifier for the entry.
int(* write)(clod_stream *self, struct clod_string *src)
int(* read)(clod_stream *self, struct clod_string *dst)
int(* close)(clod_stream *self)