Revision 3b3f24ad linux-user/syscall.c
b/linux-user/syscall.c | ||
---|---|---|
53 | 53 |
#include <sys/statfs.h> |
54 | 54 |
#include <utime.h> |
55 | 55 |
#include <sys/sysinfo.h> |
56 |
#include <sys/utsname.h> |
|
56 | 57 |
//#include <sys/user.h> |
57 | 58 |
#include <netinet/ip.h> |
58 | 59 |
#include <netinet/tcp.h> |
... | ... | |
200 | 201 |
return -ENOSYS; |
201 | 202 |
} |
202 | 203 |
#endif |
203 |
_syscall1(int,sys_uname,struct new_utsname *,buf) |
|
204 |
#if TARGET_ABI_BITS == 32 |
|
205 |
_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count); |
|
206 |
#endif |
|
207 |
#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64) |
|
208 |
_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count); |
|
209 |
#endif |
|
210 |
_syscall2(int, sys_getpriority, int, which, int, who); |
|
211 |
#if !defined (__x86_64__) |
|
212 |
_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, |
|
213 |
loff_t *, res, uint, wh); |
|
214 |
#endif |
|
215 |
_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo) |
|
216 |
_syscall3(int,sys_syslog,int,type,char*,bufp,int,len) |
|
217 |
#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill) |
|
218 |
_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig) |
|
219 |
#endif |
|
220 |
#if defined(TARGET_NR_tkill) && defined(__NR_tkill) |
|
221 |
_syscall2(int,sys_tkill,int,tid,int,sig) |
|
222 |
#endif |
|
223 |
#ifdef __NR_exit_group |
|
224 |
_syscall1(int,exit_group,int,error_code) |
|
225 |
#endif |
|
226 |
#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address) |
|
227 |
_syscall1(int,set_tid_address,int *,tidptr) |
|
228 |
#endif |
|
229 |
#if defined(USE_NPTL) |
|
230 |
#if defined(TARGET_NR_futex) && defined(__NR_futex) |
|
231 |
_syscall6(int,sys_futex,int *,uaddr,int,op,int,val, |
|
232 |
const struct timespec *,timeout,int *,uaddr2,int,val3) |
|
233 |
#endif |
|
234 |
#endif |
|
235 |
|
|
236 |
static bitmask_transtbl fcntl_flags_tbl[] = { |
|
237 |
{ TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, }, |
|
238 |
{ TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, }, |
|
239 |
{ TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, }, |
|
240 |
{ TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, }, |
|
241 |
{ TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, }, |
|
242 |
{ TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, }, |
|
243 |
{ TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, }, |
|
244 |
{ TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, }, |
|
245 |
{ TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, }, |
|
246 |
{ TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, }, |
|
247 |
{ TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, }, |
|
248 |
{ TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, }, |
|
249 |
{ TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, }, |
|
250 |
#if defined(O_DIRECT) |
|
251 |
{ TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, }, |
|
252 |
#endif |
|
253 |
{ 0, 0, 0, 0 } |
|
254 |
}; |
|
255 |
|
|
256 |
#define COPY_UTSNAME_FIELD(dest, src) \ |
|
257 |
do { \ |
|
258 |
/* __NEW_UTS_LEN doesn't include terminating null */ \ |
|
259 |
(void) strncpy((dest), (src), __NEW_UTS_LEN); \ |
|
260 |
(dest)[__NEW_UTS_LEN] = '\0'; \ |
|
261 |
} while (0) |
|
262 |
|
|
263 |
static int sys_uname(struct new_utsname *buf) |
|
264 |
{ |
|
265 |
struct utsname uts_buf; |
|
266 |
|
|
267 |
if (uname(&uts_buf) < 0) |
|
268 |
return (-1); |
|
269 |
|
|
270 |
/* |
|
271 |
* Just in case these have some differences, we |
|
272 |
* translate utsname to new_utsname (which is the |
|
273 |
* struct linux kernel uses). |
|
274 |
*/ |
|
275 |
|
|
276 |
bzero(buf, sizeof (*buf)); |
|
277 |
COPY_UTSNAME_FIELD(buf->sysname, uts_buf.sysname); |
|
278 |
COPY_UTSNAME_FIELD(buf->nodename, uts_buf.nodename); |
|
279 |
COPY_UTSNAME_FIELD(buf->release, uts_buf.release); |
|
280 |
COPY_UTSNAME_FIELD(buf->version, uts_buf.version); |
|
281 |
COPY_UTSNAME_FIELD(buf->machine, uts_buf.machine); |
|
282 |
#ifdef _GNU_SOURCE |
|
283 |
COPY_UTSNAME_FIELD(buf->domainname, uts_buf.domainname); |
|
284 |
#endif |
|
285 |
return (0); |
|
286 |
|
|
287 |
#undef COPY_UTSNAME_FIELD |
|
288 |
} |
|
289 |
|
|
290 |
static int sys_getcwd1(char *buf, size_t size) |
|
291 |
{ |
|
292 |
if (getcwd(buf, size) == NULL) { |
|
293 |
/* getcwd() sets errno */ |
|
294 |
return (-1); |
|
295 |
} |
|
296 |
return (0); |
|
297 |
} |
|
298 |
|
|
299 |
#ifdef CONFIG_ATFILE |
|
300 |
/* |
|
301 |
* Host system seems to have atfile syscall stubs available. We |
|
302 |
* now enable them one by one as specified by target syscall_nr.h. |
|
303 |
*/ |
|
304 |
|
|
305 |
#ifdef TARGET_NR_faccessat |
|
306 |
static int sys_faccessat(int dirfd, const char *pathname, int mode, int flags) |
|
307 |
{ |
|
308 |
return (faccessat(dirfd, pathname, mode, flags)); |
|
309 |
} |
|
310 |
#endif |
|
311 |
#ifdef TARGET_NR_fchmodat |
|
312 |
static int sys_fchmodat(int dirfd, const char *pathname, mode_t mode, int flags) |
|
313 |
{ |
|
314 |
return (fchmodat(dirfd, pathname, mode, flags)); |
|
315 |
} |
|
316 |
#endif |
|
317 |
#ifdef TARGET_NR_fchownat |
|
318 |
static int sys_fchownat(int dirfd, const char *pathname, uid_t owner, |
|
319 |
gid_t group, int flags) |
|
320 |
{ |
|
321 |
return (fchownat(dirfd, pathname, owner, group, flags)); |
|
322 |
} |
|
323 |
#endif |
|
324 |
#ifdef __NR_fstatat64 |
|
325 |
static int sys_fstatat64(int dirfd, const char *pathname, struct stat *buf, |
|
326 |
int flags) |
|
327 |
{ |
|
328 |
return (fstatat(dirfd, pathname, buf, flags)); |
|
329 |
} |
|
330 |
#endif |
|
331 |
#ifdef __NR_newfstatat |
|
332 |
static int sys_newfstatat(int dirfd, const char *pathname, struct stat *buf, |
|
333 |
int flags) |
|
334 |
{ |
|
335 |
return (fstatat(dirfd, pathname, buf, flags)); |
|
336 |
} |
|
337 |
#endif |
|
338 |
#ifdef TARGET_NR_futimesat |
|
339 |
static int sys_futimesat(int dirfd, const char *pathname, |
|
340 |
const struct timeval times[2]) |
|
341 |
{ |
|
342 |
return (futimesat(dirfd, pathname, times)); |
|
343 |
} |
|
344 |
#endif |
|
345 |
#ifdef TARGET_NR_linkat |
|
346 |
static int sys_linkat(int olddirfd, const char *oldpath, |
|
347 |
int newdirfd, const char *newpath, int flags) |
|
348 |
{ |
|
349 |
return (linkat(olddirfd, oldpath, newdirfd, newpath, flags)); |
|
350 |
} |
|
351 |
#endif |
|
352 |
#ifdef TARGET_NR_mkdirat |
|
353 |
static int sys_mkdirat(int dirfd, const char *pathname, mode_t mode) |
|
354 |
{ |
|
355 |
return (mkdirat(dirfd, pathname, mode)); |
|
356 |
} |
|
357 |
#endif |
|
358 |
#ifdef TARGET_NR_mknodat |
|
359 |
static int sys_mknodat(int dirfd, const char *pathname, mode_t mode, |
|
360 |
dev_t dev) |
|
361 |
{ |
|
362 |
return (mknodat(dirfd, pathname, mode, dev)); |
|
363 |
} |
|
364 |
#endif |
|
365 |
#ifdef TARGET_NR_openat |
|
366 |
static int sys_openat(int dirfd, const char *pathname, int flags, ...) |
|
367 |
{ |
|
368 |
/* |
|
369 |
* open(2) has extra parameter 'mode' when called with |
|
370 |
* flag O_CREAT. |
|
371 |
*/ |
|
372 |
if ((flags & O_CREAT) != 0) { |
|
373 |
va_list ap; |
|
374 |
mode_t mode; |
|
375 |
|
|
376 |
/* |
|
377 |
* Get the 'mode' parameter and translate it to |
|
378 |
* host bits. |
|
379 |
*/ |
|
380 |
va_start(ap, flags); |
|
381 |
mode = va_arg(ap, mode_t); |
|
382 |
mode = target_to_host_bitmask(mode, fcntl_flags_tbl); |
|
383 |
va_end(ap); |
|
384 |
|
|
385 |
return (openat(dirfd, pathname, flags, mode)); |
|
386 |
} |
|
387 |
return (openat(dirfd, pathname, flags)); |
|
388 |
} |
|
389 |
#endif |
|
390 |
#ifdef TARGET_NR_readlinkat |
|
391 |
static int sys_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz) |
|
392 |
{ |
|
393 |
return (readlinkat(dirfd, pathname, buf, bufsiz)); |
|
394 |
} |
|
395 |
#endif |
|
396 |
#ifdef TARGET_NR_renameat |
|
397 |
static int sys_renameat(int olddirfd, const char *oldpath, |
|
398 |
int newdirfd, const char *newpath) |
|
399 |
{ |
|
400 |
return (renameat(olddirfd, oldpath, newdirfd, newpath)); |
|
401 |
} |
|
402 |
#endif |
|
403 |
#ifdef TARGET_NR_symlinkat |
|
404 |
static int sys_symlinkat(const char *oldpath, int newdirfd, const char *newpath) |
|
405 |
{ |
|
406 |
return (symlinkat(oldpath, newdirfd, newpath)); |
|
407 |
} |
|
408 |
#endif |
|
409 |
#ifdef TARGET_NR_unlinkat |
|
410 |
static int sys_unlinkat(int dirfd, const char *pathname, int flags) |
|
411 |
{ |
|
412 |
return (unlinkat(dirfd, pathname, flags)); |
|
413 |
} |
|
414 |
#endif |
|
415 |
#ifdef TARGET_NR_utimensat |
|
416 |
static int sys_utimensat(int dirfd, const char *pathname, |
|
417 |
const struct timespec times[2], int flags) |
|
418 |
{ |
|
419 |
return (utimensat(dirfd, pathname, times, flags)); |
|
420 |
} |
|
421 |
#endif |
|
422 |
#else /* !CONFIG_ATFILE */ |
|
423 |
|
|
424 |
/* |
|
425 |
* Try direct syscalls instead |
|
426 |
*/ |
|
204 | 427 |
#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat) |
205 | 428 |
_syscall4(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode,int,flags) |
206 | 429 |
#endif |
... | ... | |
221 | 444 |
_syscall3(int,sys_futimesat,int,dirfd,const char *,pathname, |
222 | 445 |
const struct timeval *,times) |
223 | 446 |
#endif |
224 |
_syscall2(int,sys_getcwd1,char *,buf,size_t,size) |
|
225 |
#if TARGET_ABI_BITS == 32 |
|
226 |
_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count); |
|
227 |
#endif |
|
228 |
#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64) |
|
229 |
_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count); |
|
230 |
#endif |
|
231 |
_syscall2(int, sys_getpriority, int, which, int, who); |
|
232 |
#if !defined (__x86_64__) |
|
233 |
_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, |
|
234 |
loff_t *, res, uint, wh); |
|
447 |
#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \ |
|
448 |
defined(__NR_newfstatat) |
|
449 |
_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname, |
|
450 |
struct stat *,buf,int,flags) |
|
235 | 451 |
#endif |
236 | 452 |
#if defined(TARGET_NR_linkat) && defined(__NR_linkat) |
237 | 453 |
_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath, |
238 |
int,newdirfd,const char *,newpath,int,flags)
|
|
454 |
int,newdirfd,const char *,newpath,int,flags)
|
|
239 | 455 |
#endif |
240 | 456 |
#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat) |
241 | 457 |
_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode) |
... | ... | |
244 | 460 |
_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname, |
245 | 461 |
mode_t,mode,dev_t,dev) |
246 | 462 |
#endif |
247 |
#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \ |
|
248 |
defined(__NR_newfstatat) |
|
249 |
_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname, |
|
250 |
struct stat *,buf,int,flags) |
|
251 |
#endif |
|
252 | 463 |
#if defined(TARGET_NR_openat) && defined(__NR_openat) |
253 | 464 |
_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode) |
254 | 465 |
#endif |
... | ... | |
260 | 471 |
_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath, |
261 | 472 |
int,newdirfd,const char *,newpath) |
262 | 473 |
#endif |
263 |
_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo) |
|
264 | 474 |
#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat) |
265 | 475 |
_syscall3(int,sys_symlinkat,const char *,oldpath, |
266 | 476 |
int,newdirfd,const char *,newpath) |
267 | 477 |
#endif |
268 |
_syscall3(int,sys_syslog,int,type,char*,bufp,int,len) |
|
269 |
#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill) |
|
270 |
_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig) |
|
271 |
#endif |
|
272 |
#if defined(TARGET_NR_tkill) && defined(__NR_tkill) |
|
273 |
_syscall2(int,sys_tkill,int,tid,int,sig) |
|
274 |
#endif |
|
275 |
#ifdef __NR_exit_group |
|
276 |
_syscall1(int,exit_group,int,error_code) |
|
277 |
#endif |
|
278 |
#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address) |
|
279 |
_syscall1(int,set_tid_address,int *,tidptr) |
|
280 |
#endif |
|
281 | 478 |
#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat) |
282 | 479 |
_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags) |
283 | 480 |
#endif |
... | ... | |
285 | 482 |
_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname, |
286 | 483 |
const struct timespec *,tsp,int,flags) |
287 | 484 |
#endif |
485 |
|
|
486 |
#endif /* CONFIG_ATFILE */ |
|
487 |
|
|
488 |
#ifdef CONFIG_INOTIFY |
|
489 |
|
|
288 | 490 |
#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init) |
289 |
_syscall0(int,sys_inotify_init) |
|
491 |
static int sys_inotify_init(void) |
|
492 |
{ |
|
493 |
return (inotify_init()); |
|
494 |
} |
|
290 | 495 |
#endif |
291 | 496 |
#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch) |
292 |
_syscall3(int,sys_inotify_add_watch,int,fd,const char *,pathname,uint32_t,mask) |
|
497 |
static int sys_inotify_add_watch(int fd,const char *pathname, int32_t mask) |
|
498 |
{ |
|
499 |
return (inotify_add_watch(fd, pathname, mask)); |
|
500 |
} |
|
293 | 501 |
#endif |
294 | 502 |
#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch) |
295 |
_syscall2(int,sys_inotify_rm_watch,int,fd,uint32_t,wd) |
|
296 |
#endif |
|
297 |
#if defined(USE_NPTL) |
|
298 |
#if defined(TARGET_NR_futex) && defined(__NR_futex) |
|
299 |
_syscall6(int,sys_futex,int *,uaddr,int,op,int,val, |
|
300 |
const struct timespec *,timeout,int *,uaddr2,int,val3) |
|
301 |
#endif |
|
503 |
static int sys_inotify_rm_watch(int fd, int32_t wd) |
|
504 |
{ |
|
505 |
return (inotify_rm_watch(fd,pathname, wd)); |
|
506 |
} |
|
302 | 507 |
#endif |
508 |
#else |
|
509 |
/* Userspace can usually survive runtime without inotify */ |
|
510 |
#undef TARGET_NR_inotify_init |
|
511 |
#undef TARGET_NR_inotify_add_watch |
|
512 |
#undef TARGET_NR_inotify_rm_watch |
|
513 |
#endif /* CONFIG_INOTIFY */ |
|
514 |
|
|
303 | 515 |
|
304 | 516 |
extern int personality(int); |
305 | 517 |
extern int flock(int, int); |
... | ... | |
2580 | 2792 |
{ 0, 0, 0, 0 } |
2581 | 2793 |
}; |
2582 | 2794 |
|
2583 |
static bitmask_transtbl fcntl_flags_tbl[] = { |
|
2584 |
{ TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, }, |
|
2585 |
{ TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, }, |
|
2586 |
{ TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, }, |
|
2587 |
{ TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, }, |
|
2588 |
{ TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, }, |
|
2589 |
{ TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, }, |
|
2590 |
{ TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, }, |
|
2591 |
{ TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, }, |
|
2592 |
{ TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, }, |
|
2593 |
{ TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, }, |
|
2594 |
{ TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, }, |
|
2595 |
{ TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, }, |
|
2596 |
{ TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, }, |
|
2597 |
#if defined(O_DIRECT) |
|
2598 |
{ TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, }, |
|
2599 |
#endif |
|
2600 |
{ 0, 0, 0, 0 } |
|
2601 |
}; |
|
2602 |
|
|
2603 | 2795 |
#if defined(TARGET_I386) |
2604 | 2796 |
|
2605 | 2797 |
/* NOTE: there is really one LDT for all the threads */ |
Also available in: Unified diff