-
Notifications
You must be signed in to change notification settings - Fork 46
/
do_dprintf.c
67 lines (63 loc) · 2.02 KB
/
do_dprintf.c
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
/**
* Syscall in this file: printf
* Input: m1_p1: string parameter
* m1_p2: options parameter
*
* Return: reply_res: number of bytes being printed
*
* @author Bruce Tan
* @email [email protected]
*
* @author Paul Monigatti
* @email [email protected]
*
* @create date 2017-08-23 06:09:58
*
*/
#include <kernel/kernel.h>
#include <winix/dev.h>
#include <fs/path.h>
int do_winix_strerror(struct proc* who, struct message* msg){
char *dst;
int usr_errno, len;
if(!is_vaddr_accessible(msg->m1_p1, who))
return -EFAULT;
len = msg->m1_i1;
usr_errno = msg->m1_i2;
if(usr_errno <= 0 || usr_errno >= _NERROR)
return -EINVAL;
dst = (char*)get_physical_addr(msg->m1_p1, who);
// kdebug("errno %d from %s\n", usr_errno, who->name);
strlcpy(dst, kstr_error(usr_errno), len);
return 0;
}
/**
* printf in winix is a system call, I know it seems rediculous, but let me explain
* printf is usually a user space function that internally uses write() syscall.
* Stdout is line buffered to avoid making expensive system calls. While having
* printf() in the user space increases security and performance, printf() usually uses
* extensive amount of codes, that makes user process text size much bigger.
* Linux addresses this by using dynamic library
* , but we can't do that in winix, due to the limitation of the compiler
* since this is a small embedded architecture that has less than 1MB of memory,
* @param who
* @param m
* @return
*/
int do_winix_dprintf(struct proc *who, struct message *m){
struct filp* file;
int fd;
vptr_t* vp1, *vp2;
void *ptr, *ptr2;
fd = m->m1_i1;
vp1 = m->m1_p1;
vp2 = m->m1_p2;
if(!is_vaddr_accessible(vp1, who) || !is_vaddr_accessible(vp2, who))
return -EFAULT;
if(!is_fd_opened_and_valid(who, fd))
return -EBADF;
file = who->fp_filp[fd];
ptr = get_physical_addr(vp1,who);
ptr2 = get_physical_addr(vp2,who);
return kprintf_vm(file, ptr, ptr2, who);
}