1 /* This file contains a few general purpose utility routines.
3 * The entry points into this file are
4 * clock_timespec: ask the clock task for the real time
5 * copy_path: copy a path name from a path request from userland
6 * fetch_name: go get a path name from user space
7 * panic: something awful has occurred; MINIX cannot continue
8 * in_group: determines if group 'grp' is in rfp->fp_sgroups[]
12 #include <minix/callnr.h>
13 #include <minix/endpoint.h>
22 /*===========================================================================*
24 *===========================================================================*/
25 int copy_path(char *dest
, size_t size
)
27 /* Go get the path for a path request. Put the result in in 'dest', which
28 * should be at least PATH_MAX in size.
33 assert(size
>= PATH_MAX
);
35 name
= job_m_in
.m_lc_vfs_path
.name
;
36 len
= job_m_in
.m_lc_vfs_path
.len
;
38 if (len
> size
) { /* 'len' includes terminating-nul */
39 err_code
= ENAMETOOLONG
;
43 /* Is the string contained in the message? If not, perform a normal copy. */
44 if (len
> M_PATH_STRING_MAX
)
45 return fetch_name(name
, len
, dest
);
47 /* Just copy the path from the message */
48 strncpy(dest
, job_m_in
.m_lc_vfs_path
.buf
, len
);
50 if (dest
[len
- 1] != '\0') {
51 err_code
= ENAMETOOLONG
;
58 /*===========================================================================*
60 *===========================================================================*/
61 int fetch_name(vir_bytes path
, size_t len
, char *dest
)
63 /* Go get path and put it in 'dest'. */
66 if (len
> PATH_MAX
) { /* 'len' includes terminating-nul */
67 err_code
= ENAMETOOLONG
;
71 /* Check name length for validity. */
72 if (len
> SSIZE_MAX
) {
77 /* String is not contained in the message. Get it from user space. */
78 r
= sys_datacopy_wrapper(who_e
, path
, VFS_PROC_NR
, (vir_bytes
) dest
, len
);
84 if (dest
[len
- 1] != '\0') {
85 err_code
= ENAMETOOLONG
;
92 /*===========================================================================*
94 *===========================================================================*/
95 int isokendpt_f(const char *file
, int line
, endpoint_t endpoint
, int *proc
,
100 *proc
= _ENDPOINT_P(endpoint
);
101 if (endpoint
== NONE
) {
102 printf("VFS %s:%d: endpoint is NONE\n", file
, line
);
104 } else if (*proc
< 0 || *proc
>= NR_PROCS
) {
105 printf("VFS %s:%d: proc (%d) from endpoint (%d) out of range\n",
106 file
, line
, *proc
, endpoint
);
108 } else if ((ke
= fproc
[*proc
].fp_endpoint
) != endpoint
) {
110 assert(fproc
[*proc
].fp_pid
== PID_FREE
);
112 printf("VFS %s:%d: proc (%d) from endpoint (%d) doesn't match "
113 "known endpoint (%d)\n", file
, line
, *proc
, endpoint
,
114 fproc
[*proc
].fp_endpoint
);
115 assert(fproc
[*proc
].fp_pid
!= PID_FREE
);
121 panic("isokendpt_f failed");
123 return(failed
? EDEADEPT
: OK
);
127 /*===========================================================================*
129 *===========================================================================*/
130 struct timespec
clock_timespec(void)
132 /* This routine returns the time in seconds since 1.1.1970. MINIX is an
133 * astrophysically naive system that assumes the earth rotates at a constant
134 * rate and that such things as leap seconds do not exist.
143 r
= getuptime(&uptime
, &realtime
, &boottime
);
145 panic("clock_timespec err: %d", r
);
147 tv
.tv_sec
= boottime
+ (realtime
/system_hz
);
148 /* We do not want to overflow, and system_hz can be as high as 50kHz */
149 assert(system_hz
< LONG_MAX
/40000);
150 tv
.tv_nsec
= (realtime
%system_hz
) * 40000 / system_hz
* 25000;
154 /*===========================================================================*
156 *===========================================================================*/
157 int in_group(struct fproc
*rfp
, gid_t grp
)
161 for (i
= 0; i
< rfp
->fp_ngroups
; i
++)
162 if (rfp
->fp_sgroups
[i
] == grp
)
168 /*===========================================================================*
169 * sys_datacopy_wrapper *
170 *===========================================================================*/
171 int sys_datacopy_wrapper(endpoint_t src
, vir_bytes srcv
,
172 endpoint_t dst
, vir_bytes dstv
, size_t len
)
174 /* Safe function to copy data from or to a user buffer.
175 * VFS has to be a bit more careful as a regular copy
176 * might trigger VFS action needed by VM while it's
177 * blocked on the kernel call. This wrapper tries the
178 * copy, invokes VM itself asynchronously if necessary,
179 * then tries the copy again.
181 * This function assumes it's between VFS and a user process,
182 * and therefore one of the endpoints is SELF (VFS).
185 endpoint_t them
= NONE
;
186 vir_bytes themv
= -1;
189 r
= sys_datacopy_try(src
, srcv
, dst
, dstv
, len
);
191 if(src
== VFS_PROC_NR
) src
= SELF
;
192 if(dst
== VFS_PROC_NR
) dst
= SELF
;
194 assert(src
== SELF
|| dst
== SELF
);
196 if(src
== SELF
) { them
= dst
; themv
= dstv
; writable
= 1; }
197 if(dst
== SELF
) { them
= src
; themv
= srcv
; writable
= 0; }
199 assert(writable
>= 0);
200 assert(them
!= SELF
);
203 /* The copy has failed with EFAULT, this means the kernel has
204 * given up but it might not be a legitimate error. Ask VM.
206 if((r
=vm_vfs_procctl_handlemem(them
, themv
, len
, writable
)) != OK
) {
210 r
= sys_datacopy_try(src
, srcv
, dst
, dstv
, len
);