-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathr3_stdio.c
265 lines (246 loc) · 7.76 KB
/
r3_stdio.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
#include <unistd.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <r3_slice.h>/* В версии C2x использовать free_sized() */
/*
теория
Мы используем всего три вызова которые привязаны к системе
dtree_path
dtree_mknodat
dtree_unref
Файловая система - это некоторый отдельный процесс, который заполняет два дерева:
Директория dtee_* поиск по пути и есть возможность находить объекты по идентификаторам (dev, ino).
Основаня возможность - это отображение прямо в память без копирования, с использованием функций mmap
Each wide-oriented stream has an associated mbstate_t object that stores the current parse state
of the stream. A successful call to fgetpos( ) shall store a representation of the value of this
mbstate_t object as part of the value of the fpos_t object. A later successful call to fsetpos( ) using
the same stored fpos_t value shall restore the value of the associated mbstate_t object as well as
the position within the controlled stream
*/
/*! \defgroup _libc C Library (libc)
*/
/*! \defgroup _stdio <stdio.h> Стандартный ввод-вывод
\ingroup _libc
*/
typedef struct _Device Device_t;
typedef struct _DeviceClass DeviceClass_t;
/*! \brief
\ingroup POSIX_DEVICE_IO _libc _stdio
*/
int fclose (FILE *f){
device_flag_free(f->fildes);// освободить дескриптор файла
const DeviceClass_t* dev_class = FILE_CLASS(f);
int rc = dev_class->close(f);
Device_t* dev = (Device_t*)f->file -1;
g_slice_free(sizeof(FILE), f);// удалить OpenFileDescription Object
dtree_unref(dev);
return rc;
}
#define O_BINARY 0
/*! \brief
\ingroup POSIX_DEVICE_IO _libc _stdio
\param [in] mods
\arg r or rb Open file for reading.
\arg w or wb Truncate to zero length or create file for writing.
\arg a or ab Append; open or create file for writing at end-of-file.
\arg r+ or rb+ or r+b Open file for update (reading and writing).
\arg w+ or wb+ or w+b Truncate to zero length or create file for update.
\arg a+ or ab+ or a+b Append; open or create file for update, writing at end-of-file.
\arg x
*/
FILE * fopen (const char *restrict path, const char *restrict mods)
{
int oflag=0;
mode_t mode = 0666;// S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
if (mods[0]=='r') oflag |= O_RDONLY;
else
if (mods[0]=='w') oflag |= O_WRONLY|O_CREAT|O_TRUNC;
else
if (mods[0]=='a') oflag |= O_WRONLY|O_CREAT|O_APPEND;
mods++;
if (mods[0]=='b') oflag |= O_BINARY, mods++;//
if (mods[0]=='+') {
oflag &=~(O_RDONLY|O_WRONLY);
oflag |= O_RDWR;
mods++;
}
if (mods[0]=='b') oflag |= O_BINARY, mods++;//
if (mods[0]=='x') oflag |= O_EXCL, mods++;//
int fildes = device_flag_alloc((void*)NULL);
const char* name=NULL;
Device_t* dev = dtree_path(NULL, path, &name);// follow symlink? [EACCES] ELOOP ENXIO
if (dev==NULL) {// выйти путь не найден
return NULL;
} else
if (name==NULL){// путь разобран
if (dev->dev_id!=DEV_FIL) return NULL;// EISDIR
} else {
if (dev->dev_id!=DEV_DIR) return NULL;// ENOTDIR
if ((oflag & O_CREAT)==0) return NULL;
dev = dtree_mknodat(dev, name, mode, DEV_FIL);// EMFILE ENOMEM EROFS
}
if (dtree_nlink(dev)<0) return NULL;
struct _OpenFileDescription * f= g_slice_alloc(sizeof(struct _OpenFileDescription));// open file description
f->dev_id = DEV_FIL;
f->fildes = fildes;
f->offset = 0;
f->file = (struct _File *)(dev +1);
DEV_PTR(fildes) = (Device_t*)f;
return f;
}
/*! \brief
\ingroup POSIX_DEVICE_IO _libc _stdio
*/
int vfprintf(FILE *restrict f, const char *restrict format, va_list ap) {
return vdprintf(f->fildes, format, ap);
}
/*! \brief
\ingroup POSIX_DEVICE_IO _libc _stdio
*/
int fprintf (FILE *restrict f, const char *restrict format, ...)
{
va_list ap;
va_start(ap, format);
int rc = vfprintf(f, format, ap);
va_end(ap);
return rc;
}
/*! \breaf put a string on a stream
\ingroup POSIX_DEVICE_IO _libc _stdio
\return Upon successful completion, fputs( ) shall return a non-negative number. Otherwise, it shall
[CX] return EOF, set an error indicator for the stream
*/
int fputs (const char *restrict str, FILE *restrict f) {
const DeviceClass_t* dev_class = FILE_CLASS(f);
return dev_class->write(f, str, strlen(str));
}
/*! \brief
\ingroup POSIX_DEVICE_IO _libc _stdio
*/
inline size_t fread ( void *restrict ptr, size_t size, size_t nitems, FILE* restrict f){
const DeviceClass_t* dev_class = FILE_CLASS(f);
return dev_class->read (f, ptr, size*nitems);
}
/*! \brief
\ingroup POSIX_DEVICE_IO _libc _stdio
*/
inline size_t fwrite (const void *restrict ptr, size_t size, size_t nitems, FILE* restrict f){
const DeviceClass_t* dev_class = FILE_CLASS(f);
return dev_class->write(f, ptr, size*nitems);
}
/*! \brief
\ingroup POSIX_DEVICE_IO _libc _stdio
*/
inline int feof (FILE *f){
return (f->offset == f->file->size);
}
/*! \brief
\ingroup POSIX_FD_MGMT _libc _stdio
*/
inline int fgetpos (FILE *restrict f, fpos_t *restrict pos) {
pos->offset = f->offset;
return 0;
}
/*! \brief
\ingroup POSIX_FD_MGMT _libc _stdio
*/
inline int fsetpos(FILE * f, const fpos_t * pos){
f->offset = pos->offset;
return 0;
}
/*! \brief
\ingroup POSIX_DEVICE_IO _libc _stdio
*/
void clearerr(FILE *f) {
}
inline void rewind(FILE *f ){
f->offset = 0;
}
int fflush(FILE *f){
return 0;
}
/*! \brief
\ingroup POSIX_FD_MGMT _libc
*/
off_t ftello (FILE *f){
return f->offset;
}
/*! \brief
\ingroup POSIX_FD_MGMT _libc
*/
int fseeko (FILE *f, off_t offset, int whence){
const DeviceClass_t* dev_class = FILE_CLASS(f);
dev_class->seek(f, offset, whence);
return 0;
}
inline int fileno(FILE* restrict f){// тут есть неопределенность чем закрыть close или fclose
return f->fildes;
}
int remove(const char *path){
Device_t* dev = dtree_path(NULL, path, &path);
dtree_unref(dev);
return 0;
}
int rename(const char *old, const char *new){
///
return 0;
}
//!\}
#if defined(_POSIX_FILE_LOCKING) && (_POSIX_FILE_LOCKING>0)
static inline int _unlock_file(FILE* f, pthread_t owner){
volatile int *ptr = &f->lock;
int count=0;
if (f->owner != owner) do {
count = atomic_int_get(ptr);
if (count==0) {
f->owner =(pthread_t)0;// разблокировать может только владелец
atomic_mb();
}
} while(!atomic_int_compare_and_exchange(ptr, count, count+1));
return count;
}
static inline int _trylock_file(FILE* f, pthread_t owner){
volatile int *ptr = &f->lock;
int count;
do {
count = atomic_int_get(ptr);
if (count<=0 && f->owner!= owner) break;// заблокировано
} while(!atomic_int_compare_and_exchange(ptr, count, count-1));
if (count> 0 ){
f->owner = owner;
// atomic_mb();
}
return count;
}
/*!
\return zero for success and non-zero to indicate that the lock
cannot be acquired.
*/
int ftrylockfile(FILE *f){
pthread_t self = pthread_self();
int count = _trylock_file(f, self);
return (count<=0);
}
void funlockfile(FILE *f){
pthread_t self = pthread_self();
(void) _unlock_file(f, self);
}
void flockfile(FILE *f){
pthread_t self = pthread_self();
int count = _trylock_file(f, self);
if (count<=0) {
osEventWait(osEventSemaphre, &f->lock, osWaitForever);
}
}
#else
void flockfile(FILE *f){
}
void funlockfile(FILE *f){
}
int ftrylockfile(FILE *f){
return 0;
}
#endif