#include <stdio.h>
#include <fcntl.h>
+#include <minix/type.h>
+#include <minix/safecopies.h>
#include "log.h"
#include "../../kernel/const.h"
/*===========================================================================*
* do_diagnostics *
*===========================================================================*/
-PUBLIC int do_diagnostics(message *m)
+PUBLIC int do_diagnostics(message *m, int safe)
{
/* The LOG server handles all diagnostic messages from servers and device
* drivers. It forwards the message to the TTY driver to display it to the
* user. It also saves a copy in a local buffer so that messages can be
* reviewed at a later time.
*/
- int proc_nr_e;
vir_bytes src;
int count;
char c;
- int i = 0;
+ int i = 0, offset = 0;
static char diagbuf[10240];
- /* Change SELF to actual process number. */
- if ((proc_nr_e = m->DIAG_ENDPT) == SELF)
- m->DIAG_ENDPT = proc_nr_e = m->m_source;
-
- /* Now also make a copy for the private buffer at the LOG server, so
+ /* Also make a copy for the private buffer at the LOG server, so
* that the messages can be reviewed at a later time.
*/
- src = (vir_bytes) m->DIAG_PRINT_BUF;
+ src = (vir_bytes) m->DIAG_PRINT_BUF_G;
count = m->DIAG_BUF_COUNT;
while (count > 0 && i < sizeof(diagbuf)-1) {
- if (sys_datacopy(proc_nr_e, src, SELF, (vir_bytes) &c, 1) != OK)
- break; /* stop copying on error */
- src ++;
+ int r;
+ if(safe) {
+ r = sys_safecopyfrom(m->m_source, src, offset, (vir_bytes) &c, 1, D);
+ } else {
+ r = sys_datacopy(m->m_source, src+offset, SELF, (vir_bytes) &c, 1);
+ }
+ if(r != OK) break;
+ offset ++;
count --;
diagbuf[i++] = c;
}
FORWARD _PROTOTYPE( char *log_name, (void) );
FORWARD _PROTOTYPE( struct device *log_prepare, (int device) );
FORWARD _PROTOTYPE( int log_transfer, (int proc_nr, int opcode, off_t position,
- iovec_t *iov, unsigned nr_req) );
+ iovec_t *iov, unsigned nr_req, int safe) );
FORWARD _PROTOTYPE( int log_do_open, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( int log_cancel, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( int log_select, (struct driver *dp, message *m_ptr) );
FORWARD _PROTOTYPE( void log_signal, (struct driver *dp, message *m_ptr) );
-FORWARD _PROTOTYPE( int log_other, (struct driver *dp, message *m_ptr) );
+FORWARD _PROTOTYPE( int log_other, (struct driver *dp, message *m_ptr, int) );
FORWARD _PROTOTYPE( void log_geometry, (struct partition *entry) );
-FORWARD _PROTOTYPE( int subread, (struct logdevice *log, int count, int proc_nr, vir_bytes user_vir) );
+FORWARD _PROTOTYPE( int subread, (struct logdevice *log, int count, int proc_nr, vir_bytes user_vir, size_t, int safe) );
/* Entry points to this driver. */
PRIVATE struct driver log_dtab = {
log_name, /* current device's name */
log_do_open, /* open or mount */
do_nop, /* nothing on a close */
- do_nop, /* ioctl nop */
+ nop_ioctl, /* ioctl nop */
log_prepare, /* prepare for I/O on a given minor device */
log_transfer, /* do the I/O */
nop_cleanup, /* no need to clean up */
* subwrite *
*===========================================================================*/
PRIVATE int
-subwrite(struct logdevice *log, int count, int proc_nr, vir_bytes user_vir)
+subwrite(struct logdevice *log, int count, int proc_nr,
+ vir_bytes user_vir, size_t offset, int safe)
{
char *buf;
int r;
memcpy(buf, (char *) user_vir, count);
}
else {
- if((r=sys_vircopy(proc_nr,D,user_vir, SELF,D,(int)buf, count)) != OK)
+ if(safe) {
+ if((r=sys_safecopyfrom(proc_nr, user_vir, offset,
+ (vir_bytes)buf, count, D)) != OK)
return r;
+ } else {
+ if((r=sys_vircopy(proc_nr, D,
+ user_vir + offset, SELF,D,(int)buf, count)) != OK)
+ return r;
+ }
}
LOGINC(log->log_write, count);
* be revived.
*/
log->log_status = subread(log, log->log_iosize,
- log->log_proc_nr, log->log_user_vir);
+ log->log_proc_nr, log->log_user_vir_g,
+ log->log_user_vir_offset, log->log_safe);
notify(log->log_source);
log->log_revive_alerted = 1;
}
if(count > LOG_SIZE) skip = count - LOG_SIZE;
count -= skip;
buf += skip;
- w = subwrite(&logdevices[0], count, SELF, (vir_bytes) buf);
+ w = subwrite(&logdevices[0], count, SELF, (vir_bytes) buf,0,0);
if(w > 0 && w < count)
- subwrite(&logdevices[0], count-w, SELF, (vir_bytes) buf+w);
+ subwrite(&logdevices[0], count-w, SELF, (vir_bytes) buf+w,0,0);
return;
}
* subread *
*===========================================================================*/
PRIVATE int
-subread(struct logdevice *log, int count, int proc_nr, vir_bytes user_vir)
+subread(struct logdevice *log, int count, int proc_nr,
+ vir_bytes user_vir, size_t offset, int safe)
{
char *buf;
int r;
count = LOG_SIZE - log->log_read;
buf = log->log_buffer + log->log_read;
- if((r=sys_vircopy(SELF,D,(int)buf,proc_nr,D,user_vir, count)) != OK)
+ if(safe) {
+ if((r=sys_safecopyto(proc_nr, user_vir, offset,
+ (vir_bytes)buf, count, D)) != OK)
+ return r;
+ } else {
+ if((r=sys_vircopy(SELF,D,(int)buf,
+ proc_nr, safe ? GRANT_SEG : D, user_vir + offset, count)) != OK)
return r;
+ }
LOGINC(log->log_read, count);
log->log_size -= count;
/*===========================================================================*
* log_transfer *
*===========================================================================*/
-PRIVATE int log_transfer(proc_nr, opcode, position, iov, nr_req)
+PRIVATE int log_transfer(proc_nr, opcode, position, iov, nr_req, safe)
int proc_nr; /* process doing the request */
int opcode; /* DEV_GATHER or DEV_SCATTER */
off_t position; /* offset on device to read or write */
iovec_t *iov; /* pointer to read or write request vector */
unsigned nr_req; /* length of request vector */
+int safe; /* safe copies? */
{
/* Read or write one the driver's minor devices. */
unsigned count;
int accumulated_read = 0;
struct logdevice *log;
static int f;
+ size_t vir_offset = 0;
if(log_device < 0 || log_device >= NR_DEVS)
return EIO;
/* No data available; let caller block. */
log->log_proc_nr = proc_nr;
log->log_iosize = count;
- log->log_user_vir = user_vir;
+ log->log_user_vir_g = user_vir;
+ log->log_user_vir_offset = 0;
log->log_revive_alerted = 0;
+ log->log_safe = safe;
/* Device_caller is a global in drivers library. */
log->log_source = device_caller;
#endif
return(SUSPEND);
}
- count = subread(log, count, proc_nr, user_vir);
+ count = subread(log, count, proc_nr, user_vir, vir_offset, safe);
if(count < 0) {
return count;
}
accumulated_read += count;
} else {
- count = subwrite(log, count, proc_nr, user_vir);
+ count = subwrite(log, count, proc_nr, user_vir, vir_offset, safe);
if(count < 0)
return count;
}
}
/* Book the number of bytes transferred. */
- iov->iov_addr += count;
- if ((iov->iov_size -= count) == 0) { iov++; nr_req--; }
+ vir_offset += count;
+ if ((iov->iov_size -= count) == 0) { iov++; nr_req--; vir_offset = 0; }
}
return(OK);
}
/*============================================================================*
* log_other *
*============================================================================*/
-PRIVATE int log_other(dp, m_ptr)
+PRIVATE int log_other(dp, m_ptr, safe)
struct driver *dp;
message *m_ptr;
+int safe;
{
int r;
*/
switch(m_ptr->m_type) {
case DIAGNOSTICS: {
- r = do_diagnostics(m_ptr);
+ r = do_diagnostics(m_ptr, 0);
+ break;
+ }
+ case DIAGNOSTICS_S: {
+ r = do_diagnostics(m_ptr, 1);
break;
}
case DEV_STATUS: {