513434ef320f691f4dffecd5d579b39ce3fe67a0
[nestedvm.git] / src / org / ibex / nestedvm / support_aux.c
1 #include <string.h>
2 #include <sys/stat.h>
3 #include <sys/dirent.h>
4 #include <sys/types.h>
5 #include <utime.h>
6 #include <errno.h>
7 #include <unistd.h>
8 #include <fcntl.h>
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <signal.h>
12
13 int _syscall_set_errno(struct _reent *ptr, int err) {
14     ptr->_errno = -err;
15     return -1;
16 }
17
18 extern int _stat_r(struct _reent *, const char *, struct stat *);
19 int _access_r(struct _reent *ptr, const char *pathname, int mode) {
20     struct stat statbuf;
21     if(_stat_r(ptr,pathname,&statbuf) < 0) return -1;
22     return 0;
23 }
24
25 /* NestedVM doesn't, and probably never will, support this security related stuff */
26 uid_t getuid() { return 0; }
27 gid_t getgid() { return 0; }
28 uid_t geteuid() { return 0; }
29 gid_t getegid() { return 0; }
30 int getgroups(int gidsetlen, gid_t *gidset) {
31     if(gidsetlen) *gidset = 0;
32     return 1;
33 }
34 mode_t umask(mode_t new) { return 0022; }
35 int _chmod_r(struct _reent *ptr, const char *f, mode_t mode) { return 0; }
36 int _fchmod_r(struct _reent *ptr, int fd, mode_t mode) { return 0; }
37 int _chown_r(struct _reent *ptr, const char *f, uid_t uid, gid_t gid) { return 0; }
38 int _fchown_r(struct _reent *ptr, int fd, uid_t uid, gid_t gid) { return 0; }
39
40 #define REENT_WRAPPER0R(f,rt) \
41     extern rt _##f##_r(struct _reent *ptr); \
42     rt f() { return _##f##_r(_REENT); }
43 #define REENT_WRAPPER0(f) REENT_WRAPPER0R(f,int)
44
45 #define REENT_WRAPPER1R(f,rt,t1) \
46     extern rt _##f##_r(struct _reent *ptr, t1 a); \
47     rt f(t1 a) { return _##f##_r(_REENT,a); }
48 #define REENT_WRAPPER1(f,t1) REENT_WRAPPER1R(f,int,t1)
49
50 #define REENT_WRAPPER2R(f,rt,t1,t2) \
51     extern rt _##f##_r(struct _reent *ptr, t1 a, t2 b); \
52     rt f(t1 a, t2 b) { return _##f##_r(_REENT,a,b); }
53 #define REENT_WRAPPER2(f,t1,t2) REENT_WRAPPER2R(f,int,t1,t2)
54
55 #define REENT_WRAPPER3R(f,rt,t1,t2,t3) \
56     extern rt _##f##_r(struct _reent *ptr, t1 a, t2 b, t3 c); \
57     rt f(t1 a, t2 b, t3 c) { return _##f##_r(_REENT,a,b,c); }
58 #define REENT_WRAPPER3(f,t1,t2,t3) REENT_WRAPPER3R(f,int,t1,t2,t3)
59
60 #define REENT_WRAPPER4R(f,rt,t1,t2,t3,t4) \
61 extern rt _##f##_r(struct _reent *ptr, t1 a, t2 b, t3 c, t4 d); \
62 rt f(t1 a, t2 b, t3 c, t4 d) { return _##f##_r(_REENT,a,b,c,d); }
63 #define REENT_WRAPPER4(f,t1,t2,t3,t4) REENT_WRAPPER4R(f,int,t1,t2,t3,t4)
64
65 REENT_WRAPPER2(mkdir,const char *,mode_t)
66 REENT_WRAPPER2(access,const char *,int)
67 REENT_WRAPPER1(rmdir,const char *)
68 REENT_WRAPPER1R(sysconf,long,int)
69 REENT_WRAPPER1(chdir,const char*)
70 REENT_WRAPPER2(utime,const char *,const struct utimbuf *)
71 REENT_WRAPPER1(pipe,int *)
72 REENT_WRAPPER2(dup2,int,int)
73 REENT_WRAPPER3(waitpid,pid_t,int *,int)
74 REENT_WRAPPER2R(getcwd,char *,char *,size_t)
75 REENT_WRAPPER2R(_getcwd,char *,char *,size_t)
76 REENT_WRAPPER2(symlink,const char *,const char *)
77 REENT_WRAPPER3(readlink,const char *, char *,int)
78 REENT_WRAPPER3(chown,const char *,uid_t,gid_t)
79 REENT_WRAPPER3(fchown,int,uid_t,gid_t)
80 REENT_WRAPPER3(lchown,const char *,uid_t,gid_t)
81 REENT_WRAPPER2(chmod,const char *,mode_t)
82 REENT_WRAPPER2(fchmod,int,mode_t)
83 REENT_WRAPPER2(lstat,const char *,struct stat *)
84 REENT_WRAPPER4(getdents,int, char *, size_t,long *)
85 REENT_WRAPPER1(dup,int)
86 REENT_WRAPPER2R(pathconf,long,const char *,int)
87 REENT_WRAPPER0(vfork)
88 REENT_WRAPPER1(chroot,const char *)
89 REENT_WRAPPER3(mknod,const char *,mode_t,dev_t)
90 REENT_WRAPPER2(ftruncate,int,off_t)
91 REENT_WRAPPER1(usleep,unsigned int)
92 REENT_WRAPPER2(mkfifo,const char *, mode_t)
93 REENT_WRAPPER2(_open_socket,const char *,int)
94 REENT_WRAPPER1(_listen_socket,int)
95 REENT_WRAPPER1(_accept,int)
96
97 extern int __execve_r(struct _reent *ptr, const char *path, char *const argv[], char *const envp[]);
98 int _execve(const char *path, char *const argv[], char *const envp[]) {
99     return __execve_r(_REENT,path,argv,envp);
100 }
101
102 char *_getcwd_r(struct _reent *ptr, char *buf, size_t size) {
103     if(buf != NULL) {
104         buf = __getcwd_r(ptr,buf,size);
105         return (long)buf == -1 ? NULL : buf;
106     }
107     
108     size = 256;
109     for(;;) {
110         buf = malloc(size);
111         char *ret = __getcwd_r(ptr,buf,size);
112         if((long)ret != -1) return ret;
113         free(buf);
114         size *= 2;
115         if(ptr->_errno != ERANGE) return NULL;
116     }
117 }
118
119 pid_t _wait_r(struct _reent *ptr, int *status) {
120     return _waitpid_r(ptr,-1,status,0);
121 }
122
123 long _pathconf_r(struct _reent *ptr,const char *path, int name) {
124     switch(name) {
125         default:
126             fprintf(stderr,"WARNING: pathconf: Unknown \"name\": %d\n",name);
127             ptr->_errno = EINVAL;
128             return -1;
129     }
130 }
131
132 void sync() {
133     /* do nothing*/
134 }
135
136 int fsync(int fd) {
137     /* do nothing */
138     return 0;
139 }
140
141 char *ttyname(int fd) {
142     return isatty(fd) ? "/dev/console" : NULL;
143 }
144
145 int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) {
146     _sig_func_ptr old;
147     _sig_func_ptr new;
148     if(act) {
149         if(act->sa_flags || act->sa_mask != ~((sigset_t)0)) { errno = EINVAL; return -1; }
150         old = signal(sig,act->sa_handler);
151     } else if(oact) {
152         old = signal(sig,SIG_DFL);
153         signal(sig,old);
154     }
155     if(oact) {
156         oact->sa_handler = old;
157         oact->sa_mask = 0;
158         oact->sa_mask = ~((sigset_t)0);
159     }
160     return 0;
161 }
162
163 int sigfillset(sigset_t *set) {
164     *set = ~((sigset_t)0);
165     return 0;
166 }
167
168 int sigemptyset(sigset_t *set) {
169     *set = (sigset_t) 0;
170     return 0;
171 }
172
173 DIR *opendir(const char *path) {
174     struct stat sb;
175     int fd;
176     DIR *dir;
177     
178     fd = open(path,O_RDONLY);
179     if(fd < 0) return NULL;
180     
181     if(fstat(fd,&sb) < 0 || !S_ISDIR(sb.st_mode)) {
182         close(fd);
183         errno = ENOTDIR;
184         return NULL;
185     }
186     
187     dir = malloc(sizeof(*dir));
188     if(dir == NULL) {
189         close(fd);
190         errno = ENOMEM;
191         return NULL;
192     }
193     dir->dd_fd = fd;
194     dir->dd_buf = malloc(sizeof(struct dirent));
195     dir->dd_size = sizeof(struct dirent);
196     if(dir->dd_buf == NULL) {
197         close(fd);
198         free(dir);
199         return NULL;
200     }
201     dir->dd_loc = 0;
202     dir->dd_len = 0;
203     return dir;
204 }
205
206 struct dirent *readdir(DIR *dir) {
207     struct dirent *dp;
208     errno = 0;
209     if(dir->dd_loc == 0 || dir->dd_loc == dir->dd_len) {
210         dir->dd_len = getdents(dir->dd_fd,dir->dd_buf,dir->dd_size,NULL);
211         dir->dd_loc = 0;
212         if(dir->dd_len <= 0) { dir->dd_len = 0; return NULL; }
213     }
214     dp = (struct dirent*) (dir->dd_buf + dir->dd_loc);
215     if(dp->d_reclen == 0 || dp->d_reclen > dir->dd_len - dir->dd_loc) return NULL;
216     dir->dd_loc += dp->d_reclen;
217     return dp;
218 }
219
220 int closedir(DIR *dir) {
221     int fd = dir->dd_fd;
222     free(dir->dd_buf);
223     free(dir);
224     return close(fd);
225 }
226
227 /*
228  * Other People's Code 
229  */
230
231 /* FreeBSD's dirname/basename */
232
233 /* FIXME: Put these in a header */
234
235 /*
236  * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
237  * All rights reserved.
238  *
239  * Redistribution and use in source and binary forms, with or without
240  * modification, are permitted provided that the following conditions
241  * are met:
242  * 1. Redistributions of source code must retain the above copyright
243  *    notice, this list of conditions and the following disclaimer.
244  * 2. Redistributions in binary form must reproduce the above copyright
245  *    notice, this list of conditions and the following disclaimer in the
246  *    documentation and/or other materials provided with the distribution.
247  * 3. The name of the author may not be used to endorse or promote products
248  *    derived from this software without specific prior written permission.
249  *
250  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
251  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
252  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
253  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
254  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
255  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
256  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
257  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
258  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
259  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
260  */
261
262 char *
263 dirname(path)
264 const char *path;
265 {
266     static char bname[MAXPATHLEN];
267     register const char *endp;
268     
269     /* Empty or NULL string gets treated as "." */
270     if (path == NULL || *path == '\0') {
271         (void)strcpy(bname, ".");
272         return(bname);
273     }
274     
275     /* Strip trailing slashes */
276     endp = path + strlen(path) - 1;
277     while (endp > path && *endp == '/')
278         endp--;
279     
280     /* Find the start of the dir */
281     while (endp > path && *endp != '/')
282         endp--;
283     
284     /* Either the dir is "/" or there are no slashes */
285     if (endp == path) {
286         (void)strcpy(bname, *endp == '/' ? "/" : ".");
287         return(bname);
288     } else {
289         do {
290             endp--;
291         } while (endp > path && *endp == '/');
292     }
293     
294     if (endp - path + 2 > sizeof(bname)) {
295         errno = ENAMETOOLONG;
296         return(NULL);
297     }
298     (void)strncpy(bname, path, endp - path + 1);
299     bname[endp - path + 1] = '\0';
300     return(bname);
301 }
302
303 char *
304 basename(path)
305 const char *path;
306 {
307     static char bname[MAXPATHLEN];
308     register const char *endp, *startp;
309     
310     /* Empty or NULL string gets treated as "." */
311     if (path == NULL || *path == '\0') {
312         (void)strcpy(bname, ".");
313         return(bname);
314     }
315     
316     /* Strip trailing slashes */
317     endp = path + strlen(path) - 1;
318     while (endp > path && *endp == '/')
319         endp--;
320     
321     /* All slashes becomes "/" */
322     if (endp == path && *endp == '/') {
323         (void)strcpy(bname, "/");
324         return(bname);
325     }
326     
327     /* Find the start of the base */
328     startp = endp;
329     while (startp > path && *(startp - 1) != '/')
330         startp--;
331     
332     if (endp - startp + 2 > sizeof(bname)) {
333         errno = ENAMETOOLONG;
334         return(NULL);
335     }
336     (void)strncpy(bname, startp, endp - startp + 1);
337     bname[endp - startp + 1] = '\0';
338     return(bname);
339 }
340