tons of stuff
[nestedvm.git] / src / org / ibex / nestedvm / support_aux.c
1 #include <sys/stat.h>
2 #include <sys/dirent.h>
3 #include <sys/types.h>
4 #include <utime.h>
5 #include <errno.h>
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10
11 int _syscall_set_errno(struct _reent *ptr, int err) {
12     ptr->_errno = -err;
13     return -1;
14 }
15
16 extern int _stat_r(struct _reent *, const char *, struct stat *);
17 int _access_r(struct _reent *ptr, const char *pathname, int mode) {
18     struct stat statbuf;
19     if(_stat_r(ptr,pathname,&statbuf) < 0) return -1;
20     return 0;
21 }
22
23 /* NestedVM doesn't, and probably never will, support this security related stuff */
24 uid_t getuid() { return 0; }
25 gid_t getgid() { return 0; }
26 uid_t geteuid() { return 0; }
27 gid_t getegid() { return 0; }
28 int getgroups(int gidsetlen, gid_t *gidset) {
29     if(gidsetlen) *gidset = 0;
30     return 1;
31 }
32 mode_t umask(mode_t new) { return 0022; }
33 int _chmod_r(struct _reent *ptr, const char *f, mode_t mode) { return 0; }
34 int _fchmod_r(struct _reent *ptr, int fd, mode_t mode) { return 0; }
35 int _chown_r(struct _reent *ptr, const char *f, uid_t uid, gid_t gid) { return 0; }
36 int _fchown_r(struct _reent *ptr, int fd, uid_t uid, gid_t gid) { return 0; }
37
38 #define REENT_WRAPPER1R(f,rt,t1) \
39     extern rt _##f##_r(struct _reent *ptr, t1 a); \
40     rt f(t1 a) { return _##f##_r(_REENT,a); }
41 #define REENT_WRAPPER1(f,t1) REENT_WRAPPER1R(f,int,t1)
42
43 #define REENT_WRAPPER2R(f,rt,t1,t2) \
44     extern rt _##f##_r(struct _reent *ptr, t1 a, t2 b); \
45     rt f(t1 a, t2 b) { return _##f##_r(_REENT,a,b); }
46 #define REENT_WRAPPER2(f,t1,t2) REENT_WRAPPER2R(f,int,t1,t2)
47
48 #define REENT_WRAPPER3R(f,rt,t1,t2,t3) \
49     extern rt _##f##_r(struct _reent *ptr, t1 a, t2 b, t3 c); \
50     rt f(t1 a, t2 b, t3 c) { return _##f##_r(_REENT,a,b,c); }
51 #define REENT_WRAPPER3(f,t1,t2,t3) REENT_WRAPPER3R(f,int,t1,t2,t3)
52
53 REENT_WRAPPER2(mkdir,const char *,mode_t)
54 REENT_WRAPPER2(access,const char *,int)
55 REENT_WRAPPER1(rmdir,const char *)
56 REENT_WRAPPER1R(sysconf,long,int)
57 REENT_WRAPPER1(chdir,const char*)
58 REENT_WRAPPER2(utime,const char *,const struct utimbuf *)
59 REENT_WRAPPER1(pipe,int *)
60 REENT_WRAPPER2(dup2,int,int)
61 REENT_WRAPPER3(waitpid,pid_t,int *,int)
62 REENT_WRAPPER2R(getcwd,char *,char *,size_t)
63 REENT_WRAPPER2(symlink,const char *,const char *)
64 REENT_WRAPPER3(readlink,const char *, char *,int)
65 REENT_WRAPPER3(chown,const char *,uid_t,gid_t)
66 REENT_WRAPPER3(fchown,int,uid_t,gid_t)
67 REENT_WRAPPER2(chmod,const char *,mode_t)
68 REENT_WRAPPER2(fchmod,int,mode_t)
69 REENT_WRAPPER2(lstat,const char *,struct stat *)
70
71 extern int __execve_r(struct _reent *ptr, const char *path, char *const argv[], char *const envp[]);
72 int _execve(const char *path, char *const argv[], char *const envp[]) {
73     return __execve_r(_REENT,path,argv,envp);
74 }
75
76 static int read_fully(int fd, void *buf, size_t size) {
77     int n;
78     while(size) {
79         n = read(fd,buf,size);
80         if(n <= 0) return -1;
81         size -= n;
82         buf += n;
83     }
84     return 0;
85 }
86
87 DIR *opendir(const char *path) {
88     struct stat sb;
89     int fd;
90     DIR *dir;
91     
92     fd = open(path,O_RDONLY);
93     if(fd < 0) return NULL;
94     
95     if(fstat(fd,&sb) < 0 || !S_ISDIR(sb.st_mode)) {
96         close(fd);
97         errno = ENOTDIR;
98         return NULL;
99     }
100     
101     dir = malloc(sizeof(*dir));
102     if(dir == NULL) {
103         close(fd);
104         errno = ENOMEM;
105         return NULL;
106     }
107     dir->dd_fd = fd;
108     //dir->dd_pos = 0;
109     return dir;
110 }
111
112 int readdir_r(DIR *dir,struct dirent *entry, struct dirent **result) {
113     struct {
114         int inode;
115         int name_len;
116     } h;
117     if(dir->dd_fd < 0) return -1;
118 again:
119     if(read_fully(dir->dd_fd,&h,sizeof(h)) < 0) goto fail;
120     if(h.name_len < 0 || h.name_len >= sizeof(entry->d_name)-1) goto fail;
121     
122     entry->d_ino = h.inode;
123     if(read_fully(dir->dd_fd,entry->d_name,h.name_len) < 0) goto fail;
124     
125     entry->d_name[h.name_len] = '\0';
126     //dir->dd_pos += h.name_len + 8;
127     
128     if(result) *result = entry;
129     return 0;
130 fail:
131     if(result) *result = NULL; 
132     return -1;    
133 }
134
135 // FIXME: Rewrite all this dirent stuff in terms of a getdirentries syscall
136 static struct dirent static_dir_ent;
137
138 struct dirent *readdir(DIR *dir) { return readdir_r(dir,&static_dir_ent,NULL) == 0 ? &static_dir_ent : NULL; }
139
140 int closedir(DIR *dir) {
141     close(dir->dd_fd);
142     free(dir);
143     return 0;
144 }