~aleteoryx/muditaos

ref: 3780b4844c170a0e8f5f3b1fa615f0732009bbd8 muditaos/board/linux/libiosyscalls/src/syscalls_posix.cpp -rw-r--r-- 12.5 KiB
3780b484 — Lucjan Bryndza [EGD-5074] Add native fscore for emulator 5 years ago
                                                                                
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
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include <iosyscalls.hpp>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
#include <stdarg.h>
#include <limits.h>

#include "debug.hpp"
#include <purefs/fs/filesystem.hpp>


namespace
{
    int (*real_fprintf)(FILE *__restrict __stream, const char *__restrict __format, ...);

    void __attribute__((constructor)) _lib_posix_initialize()
    {
        real_fprintf = reinterpret_cast<decltype(real_fprintf)>(dlsym(RTLD_NEXT, "fprintf"));
        if(!real_fprintf)
        {
            abort();
        }
    }
}

extern "C" {
    using namespace vfsn::linux::internal;
    int link(const char *oldpath, const char *newpath)
    {
        TRACE_SYSCALL();
        if(redirect_to_image(oldpath))
        {
            errno = ENOSYS;
            real_fprintf(stderr, "Unsupported syscall %s\n", __PRETTY_FUNCTION__ );
            return -1;
        }
        else
        {
            auto r_link = reinterpret_cast<int (*)(const char*,const char*)>(dlsym(RTLD_NEXT,"link"));
            char tmp[PATH_MAX], tmp2[PATH_MAX];
            const auto oldp = npath_translate(oldpath,tmp);
            const auto newp = npath_translate(newpath,tmp2);
            return r_link(oldp,newp);
        }
    }
    __asm__(".symver link,link@GLIBC_2.2.5");

     int unlink(const char *name)
     {
        TRACE_SYSCALL();
        if(redirect_to_image(name))
        {
            return invoke_fs(&purefs::fs::filesystem::unlink, name);
        }
        else
        {
            char tmp[PATH_MAX];
            const auto path = npath_translate(name,tmp);
            auto r_unlink = reinterpret_cast<int (*)(const char*)>(dlsym(RTLD_NEXT,"unlink"));
            return r_unlink(path);
        }
     }
    __asm__(".symver unlink,unlink@GLIBC_2.2.5");

    int stat(const char *file, struct stat *pstat)
    {
        TRACE_SYSCALL();
        if(redirect_to_image(file))
        {
            return invoke_fs(&purefs::fs::filesystem::stat, file, *pstat);
        }
        else
        {
            char tmp[PATH_MAX];
            const auto newfile = npath_translate(file,tmp);
            auto r_xstat = reinterpret_cast<int (*)(int, const char*,struct stat*)>(dlsym(RTLD_NEXT, "__xstat"));
            return r_xstat(1,newfile,pstat);
        }
    }
    __asm__(".symver stat,stat@GLIBC_2.2.5");

    int fstat(int fd, struct stat *pstat)
    {
        TRACE_SYSCALL();
        if(is_image_fd(fd))
        {
            return invoke_fs(&purefs::fs::filesystem::fstat,fd,*pstat);
        }
        else
        {
            auto r_fxstat = reinterpret_cast<int (*)(int, int, struct stat*)>(dlsym(RTLD_NEXT, "__fxstat"));
            return r_fxstat(1,fd,pstat);
        }
    }
    __asm__(".symver fstat,fstat@GLIBC_2.2.5");

    int lstat(const char *pathname, struct stat *statbuf)
    {
        TRACE_SYSCALL();
        if(redirect_to_image(pathname))
        {
            return invoke_fs(&purefs::fs::filesystem::stat, pathname, *statbuf);
        }
        else
        {
            char tmp[PATH_MAX];
            const auto newpath = npath_translate(pathname,tmp);
            auto r_lxstat = reinterpret_cast<int (*)(int, const char*,struct stat*)>(dlsym(RTLD_NEXT, "__lxstat"));
            return r_lxstat(1,newpath,statbuf);
        }
    }
    __asm__(".symver lstat,lstat@GLIBC_2.2.5");

    int fcntl(int fd, int cmd, ... /* arg */ )
    {
        TRACE_SYSCALL();
        if(is_image_fd(fd))
        {
            TRACE_SYSCALL();
            errno = ENOSYS;
            real_fprintf(stderr, "Unsupported syscall %s\n", __PRETTY_FUNCTION__ );
            return -1;
        }
        else
        {
            uintptr_t param;
            va_list args;
            auto r_fcntl = reinterpret_cast<int (*)(int,int,...)>(dlsym(RTLD_NEXT, "fcntl"));
            va_start(args,cmd);
            param = va_arg(args,uintptr_t);
            auto ret =  r_fcntl(fd, cmd, param );
            va_end(args);
            return ret;
        }
    }
    __asm__(".symver fcntl,fcntl@GLIBC_2.2.5");

    int fcntl64(int fd, int cmd, ... /* arg */ )
    {
        TRACE_SYSCALL();
        if(is_image_fd(fd))
        {
            TRACE_SYSCALL();
            real_fprintf(stderr, "Unsupported syscall %s\n", __PRETTY_FUNCTION__ );
            errno = ENOSYS;
            return -1;
        } else {
            uintptr_t param;
            va_list args;
            auto r_fcntl = reinterpret_cast<int (*)(int,int,...)>(dlsym(RTLD_NEXT, "fcntl64"));
            va_start(args,cmd);
            param = va_arg(args,uintptr_t);
            auto ret =  r_fcntl(fd, cmd, param);
            va_end(args);
            return ret;
        }
    }
    __asm__(".symver fcntl64,fcntl64@GLIBC_2.2.5");

    int chdir(const char *path)
    {
        TRACE_SYSCALL();
        if(redirect_to_image(path))
        {
            return invoke_fs(&purefs::fs::filesystem::chdir, path);
        }
        else
        {
            char tmp[PATH_MAX];
            const auto newpath = npath_translate(path,tmp);
            auto r_chdir = reinterpret_cast<int(*)(const char*)>(dlsym(RTLD_NEXT,"chdir"));
            return r_chdir(newpath);
        }
    }
    __asm__(".symver chdir,chdir@GLIBC_2.2.5");

    int fchdir(int fd)
    {
        TRACE_SYSCALL();
        if(is_image_fd(fd))
        {
            errno = ENOSYS;
            real_fprintf(stderr, "Unsupported syscall %s\n", __PRETTY_FUNCTION__ );
            return -1;
        }
        else
        {
            auto r_fchdir = reinterpret_cast<int(*)(int)>(dlsym(RTLD_NEXT,"fchdir"));
            return r_fchdir(fd);
        }
    }
    __asm__(".symver fchdir,fchdir@GLIBC_2.2.5");

    char *getcwd(char *buf, size_t size)
    {
        TRACE_SYSCALL();
        if(redirect_to_image())
        {
            auto vfs = purefs::subsystem::vfs_core();
            if(!vfs) {
                errno = EIO;
                return nullptr;
            }
            auto xwd = vfs->getcwd();
            xwd.copy(buf,size);
            return buf;
        }
        else
        {
            auto r_getcwd = reinterpret_cast<char*(*)(char*,size_t)>(dlsym(RTLD_NEXT,"getcwd"));
            return r_getcwd(buf,size);
        }
    }
    __asm__(".symver getcwd,getcwd@GLIBC_2.2.5");

    char *getwd(char *buf)
    {
        TRACE_SYSCALL();
        if(redirect_to_image())
        {
            auto vfs = purefs::subsystem::vfs_core();
            if(!vfs) {
                errno = EIO;
                return nullptr;
            }
            auto xwd = vfs->getcwd();
            xwd.copy(buf,xwd.size());
            return buf;
        }
        else
        {
            auto r_getwd = reinterpret_cast<char*(*)(char*)>(dlsym(RTLD_NEXT,"getwd"));
            return r_getwd(buf);
        }
    }
    __asm__(".symver getwd,getwd@GLIBC_2.2.5");


    char *get_current_dir_name(void)
    {
        TRACE_SYSCALL();
        if(redirect_to_image())
        {
            auto vfs = purefs::subsystem::vfs_core();
            if(!vfs) {
                errno = EIO;
                return nullptr;
            }
            auto xwd = vfs->getcwd();
            auto ret = new char[xwd.size()+1];
            xwd.copy(ret,xwd.size());
            ret[xwd.size()] = '\0';
            return ret;
        }
        else
        {
            auto r_getrd = reinterpret_cast<char*(*)()>(dlsym(RTLD_NEXT,"get_current_dir_name"));
            return r_getrd();
        }
    }
    __asm__(".symver get_current_dir_name,get_current_dir_name@GLIBC_2.2.5");


    int rename(const char *oldpath, const char *newpath)
    {
        TRACE_SYSCALL();
        if(redirect_to_image(oldpath))
        {
            return invoke_fs(&purefs::fs::filesystem::rename, oldpath, newpath);
        }
        else
        {
            char tmp[PATH_MAX], tmp2[PATH_MAX];
            const auto oldp = npath_translate(oldpath,tmp);
            const auto newp = npath_translate(newpath,tmp2);
            auto r_rename = reinterpret_cast<int(*)(const char*,const char*)>(dlsym(RTLD_NEXT,"rename"));
            return r_rename(oldp,newp);
        }
    }
    __asm__(".symver rename,rename@GLIBC_2.2.5");

    int mkdir(const char *pathname, mode_t mode)
    {
        if(redirect_to_image(pathname))
        {
            return invoke_fs(&purefs::fs::filesystem::mkdir, pathname, mode);
        }
        else
        {
            char tmp[PATH_MAX];
            const auto path = npath_translate(pathname,tmp);
            auto r_mkdir = reinterpret_cast<int(*)(const char*,mode_t)>(dlsym(RTLD_NEXT,"mkdir"));
            return r_mkdir(path,mode);
        }
    }
    __asm__(".symver mkdir,mkdir@GLIBC_2.2.5");

    int chmod(const char *pathname, mode_t mode)
    {
        TRACE_SYSCALL();
        if(redirect_to_image(pathname))
        {
            return invoke_fs(&purefs::fs::filesystem::chmod,pathname,mode);
        }
        else
        {
            char tmp[PATH_MAX];
            const auto path = npath_translate(pathname,tmp);
            auto r_chmod = reinterpret_cast<int(*)(const char*,mode_t)>(dlsym(RTLD_NEXT,"chmod"));
            return r_chmod(path,mode);
        }
    }
    __asm__(".symver chmod,chmod@GLIBC_2.2.5");

    int fchmod(int fd, mode_t mode)
    {
        TRACE_SYSCALL();
        if(is_image_fd(fd))
        {
            return invoke_fs(&purefs::fs::filesystem::fchmod,fd,mode);
        }
        else
        {
            auto r_fchmod = reinterpret_cast<int(*)(int,mode_t)>(dlsym(RTLD_NEXT,"fchmod"));
            return r_fchmod(fd,mode);
        }
    }
    __asm__(".symver fchmod,fchmod@GLIBC_2.2.5");

    int fsync(int fd)
    {
        TRACE_SYSCALL();
        if(is_image_fd(fd))
        {
            return invoke_fs(&purefs::fs::filesystem::fsync, fd);
        }
        else
        {
            auto r_fsync = reinterpret_cast<int(*)(int)>(dlsym(RTLD_NEXT,"fsync"));
            return r_fsync(fd);
        }
    }
    __asm__(".symver fsync,fsync@GLIBC_2.2.5");

    int fdatasync(int fd)
    {
        TRACE_SYSCALL();
        return fsync(fd);
    }
    __asm__(".symver fdatasync,fdatasync@GLIBC_2.2.5");

    int symlink(const char *target, const char *linkpath)
    {
        TRACE_SYSCALL();
        if(redirect_to_image(target))
        {
            return invoke_fs(&purefs::fs::filesystem::symlink,target,linkpath);
        }
        else
        {
            char tmp[PATH_MAX], tmp2[PATH_MAX];
            const auto tgtp = npath_translate(target,tmp);
            const auto linp = npath_translate(linkpath,tmp2);
            auto r_symlink = reinterpret_cast<int(*)(const char*,const char*)>(dlsym(RTLD_NEXT,"symlink"));
            return r_symlink(tgtp,linp);
        }
    }

    __asm__(".symver symlink,symlink@GLIBC_2.2.5");

    int __symlink(const char *target, const char *linkpath)
    {
        return symlink(target,linkpath);
    }


    int fstatat(int dirfd, const char *pathname, struct stat *statbuf,
            int flags)
    {
        TRACE_SYSCALL();
        errno = ENOSYS;
        real_fprintf(stderr, "Unsupported syscall %s\n", __PRETTY_FUNCTION__ );
        return -1;
    }
    __asm__(".symver fstatat,fstatat@GLIBC_2.2.5");

    int __xstat(int ver, const char * path, struct stat * stat_buf)
    {
        if( redirect_to_image(path) )
        {
            return invoke_fs(&purefs::fs::filesystem::stat, path, *stat_buf);
        }
        else
        {
            char tmp[PATH_MAX];
            const auto newp = npath_translate(path,tmp);
            auto r_xstat = reinterpret_cast<int (*)(int,const char*,struct stat*)>(dlsym(RTLD_NEXT, "__xstat"));
            return r_xstat(ver,newp,stat_buf);
        }
    }

    int __lxstat(int ver, const char * path, struct stat * stat_buf)
    {
        if( redirect_to_image(path) )
        {
            return invoke_fs(&purefs::fs::filesystem::stat, path, *stat_buf);
        }
        else
        {
            char tmp[PATH_MAX];
            const auto newp = npath_translate(path,tmp);
            auto r_xstat = reinterpret_cast<int (*)(int,const char*,struct stat*)>(dlsym(RTLD_NEXT, "__lxstat"));
            return r_xstat(ver,newp,stat_buf);
        }
    }

    int __fxstat(int ver, int fildes, struct stat * stat_buf)
    {
        if( is_image_fd(fildes) )
        {
            return invoke_fs(&purefs::fs::filesystem::fstat, fildes, *stat_buf);
        }
        else
        {
            auto r_fxstat = reinterpret_cast<int (*)(int,int,struct stat*)>(dlsym(RTLD_NEXT, "__fxstat"));
            return r_fxstat(ver,fildes,stat_buf);
        }
    }
}