sys.c
来自「realview22.rar」· C语言 代码 · 共 517 行
C
517 行
/*
* Implementation of the full _sys() layer for Linux.
*/
#include <stddef.h> /* for size_t */
#include <errno.h>
#include <stdio.h>
#include <assert.h>
#include <rt_misc.h>
#include <rt_sys.h>
#include "asm/unistd.h"
#include "linux/types.h"
#include "linux/stat.h"
#include "linux/fcntl.h"
#include "linux/termios.h"
#include "linux/ioctl.h"
/*
* I couldn't include "linux/time.h" due to absence of asm/arch
* subdir, so I'll have to make these up myself
*/
struct timeval {
long tv_sec;
long tv_usec;
};
struct timezone {
int tz_minuteswest;
int tz_dsttime;
};
struct tms {
clock_t tms_utime;
clock_t tms_stime;
clock_t tms_cutime;
clock_t tms_cstime;
};
/*
* These system calls are direct definitions of the kernel SWI
* interface. This means they report errors in the way the actual
* kernel syscalls do, which is to return specific negative values
* such as -EFAULT and -ENOENT. Traditionally C libraries surround
* each raw syscall with a wrapper function which notices negative
* values and sets errno appropriately. Since these syscalls are
* only used within this module, though, we don't need to bother
* with this.
*/
#ifdef __thumb
#define DEF_SYSCALL_START(name) __swi_indirect_r7(0) SWI_##name(unsigned,
#define CALL_SYSCALL_START(name) SWI_##name(__NR_##name,
#define DEF_SYSCALL_END )
#define CALL_SYSCALL_END )
#define DEF_SYSCALL_0(name) __swi_indirect_r7(0) SWI_##name(unsigned)
#define CALL_SYSCALL_0(name) SWI_##name(__NR_##name)
#else
#define DEF_SYSCALL_START(name) __swi(__NR_##name) SWI_##name(
#define CALL_SYSCALL_START(name) SWI_##name(
#define DEF_SYSCALL_END )
#define CALL_SYSCALL_END )
#define DEF_SYSCALL_0(name) __swi(__NR_##name) SWI_##name()
#define CALL_SYSCALL_0(name) SWI_##name()
#endif
#define SYSCALL0(type,name) \
({DEF_SYSCALL_0(name); \
CALL_SYSCALL_0(name); })
#define SYSCALL1(type,name,type1,arg1) \
({DEF_SYSCALL_START(name) type1 DEF_SYSCALL_END; \
CALL_SYSCALL_START(name) arg1 CALL_SYSCALL_END; })
#define SYSCALL2(type,name,type1,arg1,type2,arg2) \
({DEF_SYSCALL_START(name) type1, type2 DEF_SYSCALL_END; \
CALL_SYSCALL_START(name) arg1, arg2 CALL_SYSCALL_END; })
#define SYSCALL3(type,name,type1,arg1,type2,arg2,type3,arg3) \
({DEF_SYSCALL_START(name) type1, type2, type3 DEF_SYSCALL_END; \
CALL_SYSCALL_START(name) arg1, arg2, arg3 CALL_SYSCALL_END; })
#define SYSCALL4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
({DEF_SYSCALL_START(name) type1, type2, type3, type4 DEF_SYSCALL_END; \
CALL_SYSCALL_START(name) arg1, arg2, arg3, arg4 CALL_SYSCALL_END; })
#define ioctl(d, request, term) \
SYSCALL3(int,ioctl,int,d,int,request,void *,term)
#define open(pathname, flags, mode) \
SYSCALL3(int,open,const char *,pathname,int,flags,mode_t,mode)
#define close(fd) \
SYSCALL1(int,close,int,fd)
#define read(fd, buf, count) \
SYSCALL3(ssize_t,read,int,fd,void *,buf,size_t,count)
#define write(fd, buf, count) \
SYSCALL3(long,write,int,fd,const void *,buf,size_t,count)
#define lseek(fildes, offset, whence) \
SYSCALL3(off_t,lseek,int,fildes,off_t,offset,int,whence)
#define exit(exit_code) \
SYSCALL1(long,exit,int,exit_code)
#define unlink(filename) \
SYSCALL1(int,unlink,const char *,filename)
#define gettimeofday(tv, tz) \
SYSCALL2(int,gettimeofday,struct timeval *,tv,struct timezone *,tz)
#define times(buf) \
SYSCALL1(clock_t,times,struct tms *,buf)
#define rename(oldpath, newpath) \
SYSCALL2(int,rename,const char *,oldpath,const char *,newpath)
#define execve(filename, argv, envp) \
SYSCALL3(int,execve,const char *,filename,char *const *,argv, \
char *const *, envp)
#define fork() \
SYSCALL0(int,fork)
struct rusage; /* we don't need the contents! */
#define wait4(pid, status, options, r) \
SYSCALL4(pid_t,wait4,pid_t,pid,int *,status,int,options,struct rusage *,r)
#define brk(value) \
SYSCALL1(int,brk,int,value)
/* These are set up by __main */
extern int __argc;
extern char **__argv;
extern int __stktop;
#ifdef ttywrch_c
void _ttywrch(int ch)
{
char c = ch;
write(2, &c, 1);
}
#endif
#ifdef open_c
static const int mode_map[] = {
O_RDONLY, /* 0: OPEN_R */
O_RDWR, /* 2: OPEN_PLUS */
O_WRONLY | O_CREAT | O_TRUNC, /* 4: OPEN_W */
O_RDWR | O_CREAT | O_TRUNC, /* 6: OPEN_PLUS | OPEN_W */
O_WRONLY | O_APPEND, /* 8: OPEN_A */
O_RDWR | O_APPEND, /* 10: OPEN_PLUS | OPEN_A */
};
const char __stdin_name[] = "0";
const char __stdout_name[] = "1";
const char __stderr_name[] = "2";
FILEHANDLE _sys_open(const char *name, int openmode)
{
int ret;
if (name == __stdin_name)
return 0;
else if (name == __stdout_name)
return 1;
else if (name == __stderr_name)
return 2;
/* I think that Linux doesn't care about text/binary status of the file */
openmode >>= 1;
/* Assuming "wa" or "wa+" cannot be specified */
assert(openmode < 6);
/* "u+rw,g+rw,o+r" permissions in case the file has to be created */
ret = open(name, mode_map[openmode], 0664);
if (ret < 0)
ret = -1;
return ret;
}
#endif
#ifdef close_c
int _sys_close(FILEHANDLE fh)
{
/* returns zero on success or -1 on error */
return close(fh) < 0 ? -1 : 0;
}
#endif
#ifdef read_c
int _sys_read(FILEHANDLE fh, unsigned char *buf, unsigned len, int mode)
{
int read_result;
if(len == 0) return 0;
/* read when len > SSIZE_MAX is unspecified -- Where's SSIZE_MAX??? */
read_result = read(fh,buf,len);
/* we get the number of bytes read, or -1 for an error. */
if(read_result < 0)
return -1;
/* we return something entirely different. */
return ((read_result < len) ? 0x80000000 : 0) | (len - read_result);
}
#endif
#ifdef write_c
int _sys_write(FILEHANDLE fh, const unsigned char *buf, unsigned len, int mode)
{
int write_result;
if(len == 0) return 0;
/* actually, the results of writing to a special file aren't portable, but
i'm guessing we don't care about that for now. */
write_result = write(fh,buf,len);
if(write_result < 0)
return -1;
return (len - write_result);
}
#endif
#ifdef ensure_c
int _sys_ensure(FILEHANDLE fh)
{
return 0;
}
#endif
#ifdef flen_c
long _sys_flen(FILEHANDLE fh)
{
off_t end_pos, cur_pos = lseek(fh,0,SEEK_CUR);
/* If return is -1, there was a seek error... we've probably destroyed
the world and everything. Oh well! */
if(cur_pos == (off_t)-1)
return -1;
end_pos = lseek(fh,0,SEEK_END);
if(end_pos < 0)
return -1; /* can't find the end of the file? */
if(lseek(fh,cur_pos,SEEK_SET) != cur_pos)
return -1; /* couldn't reset the file pos */
return end_pos;
}
#endif
#ifdef seek_c
int _sys_seek(FILEHANDLE fh, long pos)
{
off_t new_pos = lseek(fh,pos,SEEK_SET);
if(new_pos < 0)
return -1;
assert(new_pos == pos);
return 1;
}
#endif
#ifdef istty_c
int _sys_istty(FILEHANDLE fh)
{
struct termios term;
return (ioctl(fh,TCGETS,&term) == 0) ? 1 : 0;
}
#endif
#ifdef exit_c
void _sys_exit(int exit_code)
{
exit(exit_code);
}
#endif
#ifdef argv_c
/* override the ARM C library cmd line processing */
__value_in_regs struct __argc_argv __ARM_get_argv(void *allocparam) {
struct __argc_argv ret;
char **envp = __argv + (__argc + 1);
ret.argc = __argc;
ret.argv = __argv;
ret.r2 = (int)envp;
ret.r3 = 0;
return ret;
}
#endif
#ifdef cmdstr_c
/* We don't need to retarget this, because we've rewritten __ARM_get_argv
* which calls it. Instead, I'll just reference an undefined symbol here
* as a sort of link-time-assertion that this function is never required. */
char *_sys_command_string(char *cmd, int len)
{
extern char *__ARM_THIS_SYMBOL_SHOULD_NEVER_BE_DEFINED;
return __ARM_THIS_SYMBOL_SHOULD_NEVER_BE_DEFINED;
}
#endif
#ifdef stackheap_c
#pragma import __use_no_semihosting_swi
#pragma import __use_two_region_memory
__value_in_regs struct __initial_stackheap
__user_initial_stackheap(unsigned R0, unsigned SP,
unsigned R2, unsigned SL)
{
struct __initial_stackheap ret;
ret.heap_base = 0;
ret.heap_limit = 0;
ret.stack_base = __stktop;
ret.stack_limit = __stktop;
return ret;
}
unsigned __user_heap_extend(int zero, void **base, unsigned requested_size)
{
static int ourbrk = 0;
int ret;
requested_size = (requested_size + 0xFFF) &~ 0xFFF;
if (!ourbrk)
ourbrk = brk(0);
ret = ourbrk;
ourbrk = brk(ourbrk + requested_size);
if (ourbrk > ret) {
assert(ourbrk - ret == requested_size);
*base = (void *)ret;
return requested_size;
} else
return 0;
}
#endif
#ifdef getenv_c
char *getenv(const char *name)
{
char **envp = __argv + (__argc + 1);
while (*envp) {
char *p;
const char *q;
p = *envp;
q = name;
while (*q) {
if (*p != *q)
break;
p++, q++;
}
if (!*q && *p == '=')
return p+1;
envp++;
}
return NULL;
}
#endif
#ifdef time_c
time_t time(time_t *timer)
{
struct timeval tv;
struct timezone tz;
gettimeofday(&tv, &tz);
if (timer) *timer = tv.tv_sec;
return tv.tv_sec;
}
#endif
#ifdef clock_c
clock_t clock(void)
{
struct tms tms;
times(&tms);
return tms.tms_utime + tms.tms_stime;
}
#endif
#ifdef remove_c
int remove(const char *pathname)
{
return unlink(pathname) < 0 ? -1 : 0;
}
#endif
#ifdef rename_c
int (rename)(const char *oldname, const char *newname)
{
return rename(oldname, newname) < 0 ? -1 : 0;
}
#endif
#ifdef system_c
int system(const char *string)
{
int pid;
pid = fork();
if (pid < 0) { /* error */
return -1;
} else if (pid == 0) { /* child */
char *argv[4];
char **envp = __argv + (__argc + 1);
argv[0] = "sh";
argv[1] = "-c";
argv[2] = (char *)string;
argv[3] = NULL;
execve("/bin/sh", argv, envp);
/* ... and if that failed ... */
exit(127);
return -1; /* placate compiler; can't be reached */
} else { /* parent */
int status;
(void)wait4(pid, &status, 0, NULL);
return status;
}
}
#endif
#ifdef tmpnam_c
int _sys_tmpnam(char *name, int fileno, unsigned maxlength)
{
char *tmpdir;
int i;
extern char *getenv(const char *name);
tmpdir = getenv("TMPDIR");
if (!tmpdir)
tmpdir = "/tmp";
while (maxlength > 0 && *tmpdir)
maxlength--, *name++ = *tmpdir++;
if (maxlength > 0)
maxlength--, *name++ = '/';
if (maxlength > 0)
maxlength--, *name++ = 't';
if (maxlength > 0)
maxlength--, *name++ = 'm';
if (maxlength > 0)
maxlength--, *name++ = 'p';
for (i = 0; i < 8; i++) {
char digit = "0123456789ABCDEF"[(fileno >> 28) & 15];
if (maxlength > 0)
maxlength--, *name++ = digit;
fileno <<= 4;
}
if (maxlength > 0) {
*name = '\0';
return 1;
} else
return 0; /* failure */
}
#endif
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?