From: Ben Gras Date: Thu, 1 Feb 2007 17:50:02 +0000 (+0000) Subject: Mostly bugfixes of bugs triggered by the test set. X-Git-Tag: v3.1.3~96 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zlib_tech.html?a=commitdiff_plain;h=41e9fedf87da0b58f98e9049835e43d979ccf2b6;p=minix.git Mostly bugfixes of bugs triggered by the test set. bugfixes: SYSTEM: . removed rc->p_priv->s_flags = 0; for the priv struct shared by all user processes in get_priv(). this should only be done once. doing a SYS_PRIV_USER in sys_privctl() caused the flags of all user processes to be reset, so they were no longer PREEMPTIBLE. this happened when RS executed a policy script. (this broke test1 in the test set) VFS/MFS: . chown can change the mode of a file, and chmod arguments are only part of the full file mode so the full filemode is slightly magic. changed these calls so that the final modes are returned to VFS, so that the vnode can be kept up-to-date. (this broke test11 in the test set) MFS: . lookup() checked for sizeof(string) instead of sizeof(user_path), truncating long path names (caught by test 23) . truncate functions neglected to update ctime (this broke test16) VFS: . corner case of an empty filename lookup caused fields of a request not to be filled in in the lookup functions, not making it clear that the lookup had failed, causing messages to garbage processes, causing strange failures. (caught by test 30) . trust v_size in vnode when doing reads or writes on non-special files, truncating i/o where necessary; this is necessary for pipes, as MFS can't tell when a pipe has been truncated without it being told explicitly each time. when the last reader/writer on a pipe closes, tell FS about the new size using truncate_vn(). (this broke test 25, among others) . permission check for chdir() had disappeared; added a forbidden() call (caught by test 23) new code, shouldn't change anything: . introduced RTS_SET, RTS_UNSET, and RTS_ISSET macro's, and their LOCK variants. These macros set and clear the p_rts_flags field, causing a lot of duplicated logic like old_flags = rp->p_rts_flags; /* save value of the flags */ rp->p_rts_flags &= ~NO_PRIV; if (old_flags != 0 && rp->p_rts_flags == 0) lock_enqueue(rp); to change into the simpler RTS_LOCK_UNSET(rp, NO_PRIV); so the macros take care of calling dequeue() and enqueue() (or lock_*()), as the case may be). This makes the code a bit more readable and a bit less fragile. . removed return code from do_clocktick in CLOCK as it currently never replies . removed some debug code from VFS . fixed grant debug message in device.c preemptive checks, tests, changes: . added return code checks of receive() to SYSTEM and CLOCK . O_TRUNC should never arrive at MFS (added sanity check and removed O_TRUNC code) . user_path declared with PATH_MAX+1 to let it be null-terminated . checks in MFS to see if strings passed by VFS are null-terminated IS: . static irq name table thrown out --- diff --git a/kernel/clock.c b/kernel/clock.c index b748a3495..838f8959f 100755 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -39,7 +39,7 @@ */ FORWARD _PROTOTYPE( void init_clock, (void) ); FORWARD _PROTOTYPE( int clock_handler, (irq_hook_t *hook) ); -FORWARD _PROTOTYPE( int do_clocktick, (message *m_ptr) ); +FORWARD _PROTOTYPE( void do_clocktick, (message *m_ptr) ); FORWARD _PROTOTYPE( void load_update, (void)); /* The CLOCK's timers queue. The functions in operate on this. @@ -74,10 +74,13 @@ PUBLIC void clock_task() /* Go get a message. */ result = receive(ANY, &m); + if(result != OK) + panic("receive() failed", result); + /* Handle the request. Only clock ticks are expected. */ switch (m.m_type) { case HARD_INT: - result = do_clocktick(&m); /* handle clock tick */ + do_clocktick(&m); /* handle clock tick */ break; default: /* illegal request type */ kprintf("CLOCK: illegal request %d from %d.\n", @@ -89,7 +92,7 @@ PUBLIC void clock_task() /*===========================================================================* * do_clocktick * *===========================================================================*/ -PRIVATE int do_clocktick(m_ptr) +PRIVATE void do_clocktick(m_ptr) message *m_ptr; /* pointer to request message */ { /* Despite its name, this routine is not called on every clock tick. It @@ -103,9 +106,10 @@ message *m_ptr; /* pointer to request message */ * place in the queues. As a side-effect a new process will be scheduled. */ if (prev_ptr->p_ticks_left <= 0 && priv(prev_ptr)->s_flags & PREEMPTIBLE) { - if(prev_ptr->p_rts_flags == 0) /* if it was runnable .. */ - lock_dequeue(prev_ptr); /* take it off the queues */ - lock_enqueue(prev_ptr); /* and reinsert it again */ + if(prev_ptr->p_rts_flags == 0) { /* if it was runnable .. */ + lock_dequeue(prev_ptr); /* take it off the queues */ + lock_enqueue(prev_ptr); /* and reinsert it again */ + } } /* Check if a clock timer expired and run its watchdog function. */ @@ -115,8 +119,7 @@ message *m_ptr; /* pointer to request message */ TMR_NEVER : clock_timers->tmr_exp_time; } - /* Inhibit sending a reply. */ - return(EDONTREPLY); + return; } /*===========================================================================* diff --git a/kernel/main.c b/kernel/main.c index d0223980b..1e93aefcb 100755 --- a/kernel/main.c +++ b/kernel/main.c @@ -150,12 +150,8 @@ PUBLIC void main() } /* Set ready. The HARDWARE task is never ready. */ - if (rp->p_nr != HARDWARE) { - rp->p_rts_flags = 0; /* runnable if no flags */ - lock_enqueue(rp); /* add to scheduling queues */ - } else { - rp->p_rts_flags = NO_PRIORITY; /* prevent from running */ - } + if (rp->p_nr == HARDWARE) RTS_LOCK_SET(rp, NO_PRIORITY); + RTS_LOCK_UNSET(rp, SLOT_FREE); /* remove SLOT_FREE and schedule */ /* Code and data segments must be allocated in protected mode. */ alloc_segments(rp); diff --git a/kernel/proc.c b/kernel/proc.c index 2e6a717c9..dede6f9e4 100755 --- a/kernel/proc.c +++ b/kernel/proc.c @@ -104,7 +104,7 @@ long bit_map; /* notification event set or flags */ vir_clicks vlo, vhi; /* virtual clicks containing message to send */ #if 1 - if (caller_ptr->p_rts_flags & SLOT_FREE) + if (RTS_ISSET(caller_ptr, SLOT_FREE)) { kprintf("called by the dead?!?\n"); return EINVAL; @@ -243,10 +243,10 @@ int src_dst; /* src or dst process */ /* Check whether the last process in the chain has a dependency. If it * has not, the cycle cannot be closed and we are done. */ - if (xp->p_rts_flags & RECEIVING) { /* xp has dependency */ + if (RTS_ISSET(xp, RECEIVING)) { /* xp has dependency */ if(xp->p_getfrom_e == ANY) src_dst = ANY; else okendpt(xp->p_getfrom_e, &src_dst); - } else if (xp->p_rts_flags & SENDING) { /* xp has dependency */ + } else if (RTS_ISSET(xp, SENDING)) { /* xp has dependency */ okendpt(xp->p_sendto_e, &src_dst); } else { return(0); /* not a deadlock */ @@ -289,23 +289,22 @@ unsigned flags; /* system call flags */ dst_p = _ENDPOINT_P(dst_e); dst_ptr = proc_addr(dst_p); - if (dst_ptr->p_rts_flags & NO_ENDPOINT) return EDSTDIED; + if (RTS_ISSET(dst_ptr, NO_ENDPOINT)) return EDSTDIED; /* Check if 'dst' is blocked waiting for this message. The destination's * SENDING flag may be set when its SENDREC call blocked while sending. */ - if ( (dst_ptr->p_rts_flags & (RECEIVING | SENDING)) == RECEIVING && + if ( (RTS_ISSET(dst_ptr, RECEIVING) && !RTS_ISSET(dst_ptr, SENDING)) && (dst_ptr->p_getfrom_e == ANY || dst_ptr->p_getfrom_e == caller_ptr->p_endpoint)) { /* Destination is indeed waiting for this message. */ CopyMess(caller_ptr->p_nr, caller_ptr, m_ptr, dst_ptr, dst_ptr->p_messbuf); - if ((dst_ptr->p_rts_flags &= ~RECEIVING) == 0) enqueue(dst_ptr); + RTS_UNSET(dst_ptr, RECEIVING); } else if ( ! (flags & NON_BLOCKING)) { /* Destination is not waiting. Block and dequeue caller. */ caller_ptr->p_messbuf = m_ptr; - if (caller_ptr->p_rts_flags == 0) dequeue(caller_ptr); - caller_ptr->p_rts_flags |= SENDING; + RTS_SET(caller_ptr, SENDING); caller_ptr->p_sendto_e = dst_e; /* Process is now blocked. Put in on the destination's queue. */ @@ -344,7 +343,7 @@ unsigned flags; /* system call flags */ else { okendpt(src_e, &src_p); - if (proc_addr(src_p)->p_rts_flags & NO_ENDPOINT) return ESRCDIED; + if (RTS_ISSET(proc_addr(src_p), NO_ENDPOINT)) return ESRCDIED; } @@ -352,7 +351,7 @@ unsigned flags; /* system call flags */ * The caller's SENDING flag may be set if SENDREC couldn't send. If it is * set, the process should be blocked. */ - if (!(caller_ptr->p_rts_flags & SENDING)) { + if (!RTS_ISSET(caller_ptr, SENDING)) { /* Check if there are pending notifications, except for SENDREC. */ if (! (caller_ptr->p_misc_flags & REPLY_PENDING)) { @@ -386,7 +385,7 @@ unsigned flags; /* system call flags */ while (*xpp != NIL_PROC) { if (src_e == ANY || src_p == proc_nr(*xpp)) { #if 1 - if ((*xpp)->p_rts_flags & SLOT_FREE) + if (RTS_ISSET(*xpp, SLOT_FREE)) { kprintf("listening to the dead?!?\n"); return EINVAL; @@ -395,7 +394,7 @@ unsigned flags; /* system call flags */ /* Found acceptable message. Copy it and update status. */ CopyMess((*xpp)->p_nr, *xpp, (*xpp)->p_messbuf, caller_ptr, m_ptr); - if (((*xpp)->p_rts_flags &= ~SENDING) == 0) enqueue(*xpp); + RTS_UNSET(*xpp, SENDING); *xpp = (*xpp)->p_q_link; /* remove from queue */ return(OK); /* report success */ } @@ -409,8 +408,7 @@ unsigned flags; /* system call flags */ if ( ! (flags & NON_BLOCKING)) { caller_ptr->p_getfrom_e = src_e; caller_ptr->p_messbuf = m_ptr; - if (caller_ptr->p_rts_flags == 0) dequeue(caller_ptr); - caller_ptr->p_rts_flags |= RECEIVING; + RTS_SET(caller_ptr, RECEIVING); return(OK); } else { return(ENOTREADY); @@ -431,7 +429,7 @@ int dst; /* which process to notify */ /* Check to see if target is blocked waiting for this message. A process * can be both sending and receiving during a SENDREC system call. */ - if ((dst_ptr->p_rts_flags & (RECEIVING|SENDING)) == RECEIVING && + if ( (RTS_ISSET(dst_ptr, RECEIVING) && !RTS_ISSET(dst_ptr, SENDING)) && ! (dst_ptr->p_misc_flags & REPLY_PENDING) && (dst_ptr->p_getfrom_e == ANY || dst_ptr->p_getfrom_e == caller_ptr->p_endpoint)) { @@ -443,8 +441,7 @@ int dst; /* which process to notify */ BuildMess(&m, proc_nr(caller_ptr), dst_ptr); CopyMess(proc_nr(caller_ptr), proc_addr(HARDWARE), &m, dst_ptr, dst_ptr->p_messbuf); - dst_ptr->p_rts_flags &= ~RECEIVING; /* deblock destination */ - if (dst_ptr->p_rts_flags == 0) enqueue(dst_ptr); + RTS_UNSET(dst_ptr, RECEIVING); return(OK); } diff --git a/kernel/proc.h b/kernel/proc.h index 9f0a264a4..4ce8cc6a4 100755 --- a/kernel/proc.h +++ b/kernel/proc.h @@ -12,7 +12,7 @@ #include #include "const.h" #include "priv.h" - + struct proc { struct stackframe_s p_reg; /* process' registers saved in stack frame */ struct segframe p_seg; /* segment descriptors */ @@ -60,6 +60,50 @@ struct proc { #define NO_PRIV 0x80 /* keep forked system process from running */ #define NO_ENDPOINT 0x100 /* process cannot send or receive messages */ +/* These runtime flags can be tested and manipulated by these macros. */ + +#define RTS_ISSET(rp, f) (((rp)->p_rts_flags & (f)) == (f)) + + +/* Set flag and dequeue if the process was runnable. */ +#define RTS_SET(rp, f) \ + do { \ + if(!(rp)->p_rts_flags) { dequeue(rp); } \ + (rp)->p_rts_flags |= (f); \ + } while(0) + +/* Clear flag and enqueue if the process was not runnable but is now. */ +#define RTS_UNSET(rp, f) \ + do { \ + int rts; \ + rts = (rp)->p_rts_flags; \ + (rp)->p_rts_flags &= ~(f); \ + if(rts && !(rp)->p_rts_flags) { enqueue(rp); } \ + } while(0) + +/* Set flag and dequeue if the process was runnable. */ +#define RTS_LOCK_SET(rp, f) \ + do { \ + if(!(rp)->p_rts_flags) { lock_dequeue(rp); } \ + (rp)->p_rts_flags |= (f); \ + } while(0) + +/* Clear flag and enqueue if the process was not runnable but is now. */ +#define RTS_LOCK_UNSET(rp, f) \ + do { \ + int rts; \ + rts = (rp)->p_rts_flags; \ + (rp)->p_rts_flags &= ~(f); \ + if(rts && !(rp)->p_rts_flags) { lock_enqueue(rp); } \ + } while(0) + +/* Set flags to this value. */ +#define RTS_LOCK_SETFLAGS(rp, f) \ + do { \ + if(!(rp)->p_rts_flags && (f)) { lock_dequeue(rp); } \ + (rp)->p_rts_flags = (f); \ + } while(0) + /* Misc flags */ #define REPLY_PENDING 0x01 /* reply to IPC_REQUEST is pending */ #define MF_VM 0x08 /* process uses VM */ diff --git a/kernel/system.c b/kernel/system.c index 68d577d0b..fc7f94f25 100755 --- a/kernel/system.c +++ b/kernel/system.c @@ -30,6 +30,7 @@ #include "debug.h" #include "kernel.h" #include "system.h" +#include "proc.h" #include #include #include @@ -67,8 +68,9 @@ PUBLIC void sys_task() initialize(); while (TRUE) { + int r; /* Get work. Block and wait until a request message arrives. */ - receive(ANY, &m); + if((r=receive(ANY, &m)) != OK) panic("system: receive() failed", r); sys_call_code = (unsigned) m.m_type; call_nr = sys_call_code - KERNEL_CALL; who_e = m.m_source; @@ -216,7 +218,8 @@ int proc_type; /* system or user process flag */ } else { rc->p_priv = &priv[USER_PRIV_ID]; /* use shared slot */ rc->p_priv->s_proc_nr = INIT_PROC_NR; /* set association */ - rc->p_priv->s_flags = 0; /* no initial flags */ + + /* s_flags of this shared structure are to be once at system startup. */ } return(OK); } @@ -292,9 +295,8 @@ int sig_nr; /* signal to be sent, 1 to _NSIG */ rp = proc_addr(proc_nr); if (! sigismember(&rp->p_pending, sig_nr)) { sigaddset(&rp->p_pending, sig_nr); - if (! (rp->p_rts_flags & SIGNALED)) { /* other pending */ - if (rp->p_rts_flags == 0) lock_dequeue(rp); /* make not ready */ - rp->p_rts_flags |= SIGNALED | SIG_PENDING; /* update flags */ + if (! (RTS_ISSET(rp, SIGNALED))) { /* other pending */ + RTS_LOCK_SET(rp, SIGNALED | SIG_PENDING); send_sig(PM_PROC_NR, SIGKSIG); } } @@ -473,13 +475,12 @@ register struct proc *rc; /* slot of process to clean up */ if(isemptyp(rc)) panic("clear_proc: empty process", proc_nr(rc)); /* Make sure that the exiting process is no longer scheduled. */ - if (rc->p_rts_flags == 0) lock_dequeue(rc); - rc->p_rts_flags |= NO_ENDPOINT; + RTS_LOCK_SET(rc, NO_ENDPOINT); /* If the process happens to be queued trying to send a * message, then it must be removed from the message queues. */ - if (rc->p_rts_flags & SENDING) { + if (RTS_ISSET(rc, SENDING)) { int target_proc; okendpt(rc->p_sendto_e, &target_proc); @@ -511,21 +512,20 @@ register struct proc *rc; /* slot of process to clean up */ unset_sys_bit(priv(rp)->s_notify_pending, priv(rc)->s_id); /* Check if process is receiving from exiting process. */ - if ((rp->p_rts_flags & RECEIVING) && rp->p_getfrom_e == rc->p_endpoint) { + if (RTS_ISSET(rp, RECEIVING) && rp->p_getfrom_e == rc->p_endpoint) { rp->p_reg.retreg = ESRCDIED; /* report source died */ - rp->p_rts_flags &= ~RECEIVING; /* no longer receiving */ + RTS_LOCK_UNSET(rp, RECEIVING); /* no longer receiving */ #if DEBUG_ENABLE_IPC_WARNINGS kprintf("Proc %d receive dead src %d\n", proc_nr(rp), proc_nr(rc)); #endif - if (rp->p_rts_flags == 0) lock_enqueue(rp);/* let process run again */ } - if ((rp->p_rts_flags & SENDING) && rp->p_sendto_e == rc->p_endpoint) { + if (RTS_ISSET(rp, SENDING) && + rp->p_sendto_e == rc->p_endpoint) { rp->p_reg.retreg = EDSTDIED; /* report destination died */ - rp->p_rts_flags &= ~SENDING; /* no longer sending */ + RTS_LOCK_UNSET(rp, SENDING); #if DEBUG_ENABLE_IPC_WARNINGS kprintf("Proc %d send dead dst %d\n", proc_nr(rp), proc_nr(rc)); #endif - if (rp->p_rts_flags == 0) lock_enqueue(rp);/* let process run again */ } } } diff --git a/kernel/system/do_endksig.c b/kernel/system/do_endksig.c index 642a77669..1e62dc05b 100644 --- a/kernel/system/do_endksig.c +++ b/kernel/system/do_endksig.c @@ -31,12 +31,11 @@ message *m_ptr; /* pointer to request message */ return EINVAL; rp = proc_addr(proc); - if (! (rp->p_rts_flags & SIG_PENDING)) return(EINVAL); + if (!RTS_ISSET(rp, SIG_PENDING)) return(EINVAL); /* PM has finished one kernel signal. Perhaps process is ready now? */ - if (! (rp->p_rts_flags & SIGNALED)) /* new signal arrived */ - if ((rp->p_rts_flags &= ~SIG_PENDING)==0) /* remove pending flag */ - lock_enqueue(rp); /* ready if no flags */ + if (!RTS_ISSET(rp, SIGNALED)) /* new signal arrived */ + RTS_LOCK_UNSET(rp, SIG_PENDING); /* remove pending flag */ return(OK); } diff --git a/kernel/system/do_exec.c b/kernel/system/do_exec.c index 909d63f3e..dca66d9c1 100644 --- a/kernel/system/do_exec.c +++ b/kernel/system/do_exec.c @@ -40,8 +40,7 @@ register message *m_ptr; /* pointer to request message */ (LDT_SIZE - EXTRA_LDT_INDEX) * sizeof(rp->p_seg.p_ldt[0])); #endif rp->p_reg.pc = (reg_t) m_ptr->PR_IP_PTR; /* set pc */ - rp->p_rts_flags &= ~RECEIVING; /* PM does not reply to EXEC call */ - if (rp->p_rts_flags == 0) lock_enqueue(rp); + RTS_LOCK_UNSET(rp, RECEIVING); /* PM does not reply to EXEC call */ /* Save command name for debugging, ps(1) output, etc. */ phys_name = numap_local(who_p, (vir_bytes) m_ptr->PR_NAME_PTR, (vir_bytes) P_NAME_LEN - 1); diff --git a/kernel/system/do_exit.c b/kernel/system/do_exit.c index 165ea855c..99d6d6c68 100644 --- a/kernel/system/do_exit.c +++ b/kernel/system/do_exit.c @@ -52,7 +52,6 @@ register struct proc *rc; /* slot of process to clean up */ register struct proc **xpp; /* iterate over caller queue */ int i; int sys_id; - char saved_rts_flags; /* Don't clear if already cleared. */ if(isemptyp(rc)) return; @@ -63,8 +62,10 @@ register struct proc *rc; /* slot of process to clean up */ /* Turn off any alarm timers at the clock. */ reset_timer(&priv(rc)->s_alarm_timer); - /* Make sure that the exiting process is no longer scheduled. */ - if (rc->p_rts_flags == 0) lock_dequeue(rc); + /* Make sure that the exiting process is no longer scheduled, + * and mark slot as FREE. + */ + RTS_LOCK_SETFLAGS(rc, SLOT_FREE); /* Check the table with IRQ hooks to see if hooks should be released. */ for (i=0; i < NR_IRQ_HOOKS; i++) { @@ -80,8 +81,6 @@ register struct proc *rc; /* slot of process to clean up */ * this point. All important fields are reinitialized when the * slots are assigned to another, new process. */ - saved_rts_flags = rc->p_rts_flags; - rc->p_rts_flags = SLOT_FREE; if (priv(rc)->s_flags & SYS_PROC) priv(rc)->s_proc_nr = NONE; /* Clean up virtual memory */ diff --git a/kernel/system/do_fork.c b/kernel/system/do_fork.c index b1daba701..63016e146 100644 --- a/kernel/system/do_fork.c +++ b/kernel/system/do_fork.c @@ -26,7 +26,7 @@ register message *m_ptr; /* pointer to request message */ register struct proc *rpc; /* child process pointer */ struct proc *rpp; /* parent process pointer */ struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */ - int i, gen; + int i, gen, r; int p_proc; if(!isokendpt(m_ptr->PR_ENDPT, &p_proc)) @@ -51,10 +51,6 @@ register message *m_ptr; /* pointer to request message */ rpc->p_nr = m_ptr->PR_SLOT; /* this was obliterated by copy */ rpc->p_endpoint = _ENDPOINT(gen, rpc->p_nr); /* new endpoint of slot */ - /* Only one in group should have SIGNALED, child doesn't inherit tracing. */ - rpc->p_rts_flags &= ~(SIGNALED | SIG_PENDING | P_STOP); - sigemptyset(&rpc->p_pending); - rpc->p_reg.retreg = 0; /* child sees pid = 0 to know it is child */ rpc->p_user_time = 0; /* set all the accounting times to 0 */ rpc->p_sys_time = 0; @@ -79,7 +75,13 @@ register message *m_ptr; /* pointer to request message */ m_ptr->PR_ENDPT = rpc->p_endpoint; /* Install new map */ - return newmap(rpc, map_ptr); + r = newmap(rpc, map_ptr); + + /* Only one in group should have SIGNALED, child doesn't inherit tracing. */ + RTS_LOCK_UNSET(rpc, (SIGNALED | SIG_PENDING | P_STOP)); + sigemptyset(&rpc->p_pending); + + return r; } #endif /* USE_FORK */ diff --git a/kernel/system/do_getksig.c b/kernel/system/do_getksig.c index 95d85a507..1bf0e165f 100644 --- a/kernel/system/do_getksig.c +++ b/kernel/system/do_getksig.c @@ -29,12 +29,12 @@ message *m_ptr; /* pointer to request message */ /* Find the next process with pending signals. */ for (rp = BEG_USER_ADDR; rp < END_PROC_ADDR; rp++) { - if (rp->p_rts_flags & SIGNALED) { + if (RTS_ISSET(rp, SIGNALED)) { /* store signaled process' endpoint */ m_ptr->SIG_ENDPT = rp->p_endpoint; m_ptr->SIG_MAP = rp->p_pending; /* pending signals map */ sigemptyset(&rp->p_pending); /* ball is in PM's court */ - rp->p_rts_flags &= ~SIGNALED; /* blocked by SIG_PENDING */ + RTS_LOCK_UNSET(rp, SIGNALED); /* blocked by SIG_PENDING */ return(OK); } } diff --git a/kernel/system/do_newmap.c b/kernel/system/do_newmap.c index b595334a7..a179f5631 100644 --- a/kernel/system/do_newmap.c +++ b/kernel/system/do_newmap.c @@ -20,7 +20,6 @@ message *m_ptr; /* pointer to request message */ register struct proc *rp; /* process whose map is to be loaded */ struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */ phys_bytes src_phys; /* physical address of map at the PM */ - int old_flags; /* value of flags before modification */ int proc; map_ptr = (struct mem_map *) m_ptr->PR_MEM_PTR; @@ -41,7 +40,6 @@ struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */ { /* Fetch the memory map from PM. */ phys_bytes src_phys; /* physical address of map at the PM */ - int old_flags; /* value of flags before modification */ int proc; /* Copy the map from PM. */ @@ -52,8 +50,6 @@ struct mem_map *map_ptr; /* virtual address of map inside caller (PM) */ (phys_bytes)sizeof(rp->p_memmap)); alloc_segments(rp); - old_flags = rp->p_rts_flags; /* save the previous value of the flags */ - if (old_flags != 0 && rp->p_rts_flags == 0) lock_enqueue(rp); return(OK); } diff --git a/kernel/system/do_nice.c b/kernel/system/do_nice.c index 64a23ab78..e31403fc3 100644 --- a/kernel/system/do_nice.c +++ b/kernel/system/do_nice.c @@ -28,10 +28,8 @@ PUBLIC int do_nice(message *m_ptr) rp = proc_addr(proc_nr); if (pri == PRIO_STOP) { - /* Take process off the scheduling queues. */ - if(rp->p_rts_flags == 0) lock_dequeue(rp); - rp->p_rts_flags |= NO_PRIORITY; + RTS_LOCK_SET(rp, NO_PRIORITY); return(OK); } else if (pri >= PRIO_MIN && pri <= PRIO_MAX) { @@ -48,10 +46,9 @@ PUBLIC int do_nice(message *m_ptr) /* Make sure the process is not running while changing its priority. * Put the process back in its new queue if it is runnable. */ - if(rp->p_rts_flags == 0) lock_dequeue(rp); - rp->p_rts_flags &= ~NO_PRIORITY; + RTS_LOCK_SET(rp, NO_PRIORITY); rp->p_max_priority = rp->p_priority = new_q; - if (! rp->p_rts_flags) lock_enqueue(rp); + RTS_LOCK_UNSET(rp, NO_PRIORITY); return(OK); } diff --git a/kernel/system/do_privctl.c b/kernel/system/do_privctl.c index 50231a458..d3ffe07d0 100644 --- a/kernel/system/do_privctl.c +++ b/kernel/system/do_privctl.c @@ -28,7 +28,6 @@ message *m_ptr; /* pointer to request message */ register struct priv *sp; int proc_nr; int priv_id; - int old_flags; int i; phys_bytes caller_phys, kernel_phys; struct io_range io_range; @@ -49,7 +48,7 @@ message *m_ptr; /* pointer to request message */ switch(m_ptr->CTL_REQUEST) { case SYS_PRIV_INIT: - if (! (rp->p_rts_flags & NO_PRIV)) return(EPERM); + if (! RTS_ISSET(rp, NO_PRIV)) return(EPERM); /* Make sure this process has its own privileges structure. This may * fail, since there are only a limited number of system processes. @@ -136,25 +135,17 @@ message *m_ptr; /* pointer to request message */ } /* Done. Privileges have been set. Allow process to run again. */ - old_flags = rp->p_rts_flags; /* save value of the flags */ - rp->p_rts_flags &= ~NO_PRIV; - if (old_flags != 0 && rp->p_rts_flags == 0) lock_enqueue(rp); + RTS_LOCK_UNSET(rp, NO_PRIV); return(OK); case SYS_PRIV_USER: - if (! (rp->p_rts_flags & NO_PRIV)) return(EPERM); - - /* Make this process an ordinary user process. - */ + /* Make this process an ordinary user process. */ + if (!RTS_ISSET(rp, NO_PRIV)) return(EPERM); if ((i=get_priv(rp, 0)) != OK) return(i); - - /* Done. Privileges have been set. Allow process to run again. */ - old_flags = rp->p_rts_flags; /* save value of the flags */ - rp->p_rts_flags &= ~NO_PRIV; - if (old_flags != 0 && rp->p_rts_flags == 0) lock_enqueue(rp); + RTS_LOCK_UNSET(rp, NO_PRIV); return(OK); case SYS_PRIV_ADD_IO: - if (rp->p_rts_flags & NO_PRIV) + if (RTS_ISSET(rp, NO_PRIV)) return(EPERM); /* Only system processes get I/O resources? */ @@ -180,7 +171,7 @@ message *m_ptr; /* pointer to request message */ return OK; case SYS_PRIV_ADD_MEM: - if (rp->p_rts_flags & NO_PRIV) + if (RTS_ISSET(rp, NO_PRIV)) return(EPERM); /* Only system processes get memory resources? */ @@ -208,7 +199,7 @@ message *m_ptr; /* pointer to request message */ return OK; case SYS_PRIV_ADD_IRQ: - if (rp->p_rts_flags & NO_PRIV) + if (RTS_ISSET(rp, NO_PRIV)) return(EPERM); /* Only system processes get IRQs? */ diff --git a/kernel/system/do_safecopy.c b/kernel/system/do_safecopy.c index 38bc2b19b..efe89395a 100644 --- a/kernel/system/do_safecopy.c +++ b/kernel/system/do_safecopy.c @@ -61,7 +61,7 @@ endpoint_t *e_granter; /* new granter (magic grants) */ * EINVAL for grant-out-of-range, in case this turns out to be * interesting information.) */ - if((granter_proc->p_rts_flags & NO_PRIV) || !(priv(granter_proc)) || + if(RTS_ISSET(granter_proc, NO_PRIV) || !(priv(granter_proc)) || priv(granter_proc)->s_grant_table < 1) { kprintf("grant verify failed in ep %d proc %d: " "no priv table, or no grant table\n", diff --git a/kernel/system/do_setgrant.c b/kernel/system/do_setgrant.c index 7f353e33a..39044bab4 100644 --- a/kernel/system/do_setgrant.c +++ b/kernel/system/do_setgrant.c @@ -22,7 +22,7 @@ message *m_ptr; rp = proc_addr(who_p); /* Copy grant table set in priv. struct. */ - if ((rp->p_rts_flags & NO_PRIV) || !(priv(rp))) { + if (RTS_ISSET(rp, NO_PRIV) || !(priv(rp))) { r = EPERM; } else { _K_SET_GRANT_TABLE(rp, diff --git a/kernel/system/do_sigsend.c b/kernel/system/do_sigsend.c index b118edb34..0b37bac89 100644 --- a/kernel/system/do_sigsend.c +++ b/kernel/system/do_sigsend.c @@ -93,10 +93,10 @@ message *m_ptr; /* pointer to request message */ rp->p_reg.pc = (reg_t) smsg.sm_sighandler; /* Reschedule if necessary. */ - if(rp->p_rts_flags & NO_PRIORITY) { - rp->p_rts_flags &= ~NO_PRIORITY; - if (rp->p_rts_flags == 0) lock_enqueue(rp); - } else kprintf("system: warning: sigsend a running process\n"); + if(RTS_ISSET(rp, NO_PRIORITY)) + RTS_LOCK_UNSET(rp, NO_PRIORITY); + else + kprintf("system: warning: sigsend a running process\n"); return(OK); } diff --git a/kernel/system/do_trace.c b/kernel/system/do_trace.c index 19299b3af..0e12f0ba5 100644 --- a/kernel/system/do_trace.c +++ b/kernel/system/do_trace.c @@ -55,8 +55,7 @@ register message *m_ptr; if (isemptyp(rp)) return(EIO); switch (tr_request) { case T_STOP: /* stop process */ - if (rp->p_rts_flags == 0) lock_dequeue(rp); - rp->p_rts_flags |= P_STOP; + RTS_LOCK_SET(rp, P_STOP); rp->p_reg.psw &= ~TRACEBIT; /* clear trace bit */ return(OK); @@ -126,15 +125,13 @@ register message *m_ptr; break; case T_RESUME: /* resume execution */ - rp->p_rts_flags &= ~P_STOP; - if (rp->p_rts_flags == 0) lock_enqueue(rp); + RTS_LOCK_UNSET(rp, P_STOP); m_ptr->CTL_DATA = 0; break; case T_STEP: /* set trace bit */ rp->p_reg.psw |= TRACEBIT; - rp->p_rts_flags &= ~P_STOP; - if (rp->p_rts_flags == 0) lock_enqueue(rp); + RTS_LOCK_UNSET(rp, P_STOP); m_ptr->CTL_DATA = 0; break; diff --git a/servers/is/dmp_kernel.c b/servers/is/dmp_kernel.c index 43c355d1a..2ac0f3daf 100644 --- a/servers/is/dmp_kernel.c +++ b/servers/is/dmp_kernel.c @@ -137,24 +137,6 @@ PUBLIC void irqtab_dmp() struct irq_hook irq_hooks[NR_IRQ_HOOKS]; int irq_actids[NR_IRQ_VECTORS]; struct irq_hook *e; /* irq tab entry */ - char *irq[] = { - "clock", /* 00 */ - "keyboard", /* 01 */ - "cascade", /* 02 */ - "rs232", /* 03 */ - "rs232", /* 04 */ - "NIC(eth)", /* 05 */ - "floppy", /* 06 */ - "printer", /* 07 */ - "", /* 08 */ - "", /* 09 */ - "", /* 10 */ - "", /* 11 */ - "", /* 12 */ - "", /* 13 */ - "at_wini_0", /* 14 */ - "at_wini_1", /* 15 */ - }; if ((r = sys_getirqhooks(irq_hooks)) != OK) { report("IS","warning: couldn't get copy of irq hooks", r); @@ -173,7 +155,7 @@ PUBLIC void irqtab_dmp() #endif printf("IRQ policies dump shows use of kernel's IRQ hooks.\n"); - printf("-h.id- -proc.nr- -IRQ vector (nr.)- -policy- -notify id-\n"); + printf("-h.id- -proc.nr- -irq nr- -policy- -notify id-\n"); for (i=0; iproc_nr_e); - printf(" %9.9s (%02d) ", irq[e->irq], e->irq); + printf(" (%02d) ", e->irq); printf(" %s", (e->policy & IRQ_REENABLE) ? "reenable" : " - "); printf(" %d", e->notify_id); if (irq_actids[e->irq] & (1 << i)) diff --git a/servers/mfs/glo.h b/servers/mfs/glo.h index 36cd88329..01686272c 100644 --- a/servers/mfs/glo.h +++ b/servers/mfs/glo.h @@ -33,7 +33,7 @@ EXTERN int SELF_E; EXTERN struct inode *chroot_dir; EXTERN short path_processed; /* number of characters processed */ -EXTERN char user_path[PATH_MAX]; /* pathname to be processed */ +EXTERN char user_path[PATH_MAX+1]; /* pathname to be processed */ EXTERN char *vfs_slink_storage; EXTERN int symloop; diff --git a/servers/mfs/link.c b/servers/mfs/link.c index 0e76712b5..13db3af03 100644 --- a/servers/mfs/link.c +++ b/servers/mfs/link.c @@ -586,6 +586,7 @@ off_t newsize; /* inode must become this size */ /* Next correct the inode size. */ if(!waspipe) rip->i_size = newsize; else wipe_inode(rip); /* Pipes can only be truncated to 0. */ + rip->i_update |= CTIME | MTIME; rip->i_dirt = DIRTY; return OK; @@ -642,6 +643,9 @@ off_t start, end; /* range of bytes to free (end uninclusive) */ for(p = nextblock(start, zone_size)/zone_size; p < e; p ++) write_map(rip, p*zone_size, NO_ZONE, WMAP_FREE); + rip->i_update |= CTIME | MTIME; + rip->i_dirt = DIRTY; + return OK; } diff --git a/servers/mfs/open.c b/servers/mfs/open.c index b2889e21d..eb5245b9c 100644 --- a/servers/mfs/open.c +++ b/servers/mfs/open.c @@ -91,6 +91,8 @@ printf("MFS(%d) get_inode by open() failed\n", SELF_E); case I_REGULAR: /* Truncate regular file if O_TRUNC. */ if (oflags & O_TRUNC) { + panic(__FILE__, "O_TRUNC in mfs.", oflags); +#if 0 if ((r = forbidden(rip, W_BIT)) !=OK) break; truncate_inode(rip, 0); wipe_inode(rip); @@ -99,6 +101,7 @@ printf("MFS(%d) get_inode by open() failed\n", SELF_E); * cache flush. */ rw_inode(rip, WRITING); +#endif } break; diff --git a/servers/mfs/path.c b/servers/mfs/path.c index e5459c3cf..9158f8def 100644 --- a/servers/mfs/path.c +++ b/servers/mfs/path.c @@ -43,7 +43,7 @@ PUBLIC int lookup() /* Check length. */ len = fs_m_in.REQ_PATH_LEN; - if(len > sizeof(string)) return E2BIG; /* too big for buffer */ + if(len > sizeof(user_path)) return E2BIG; /* too big for buffer */ if(len < 1) return EINVAL; /* too small for \0 */ /* Copy the pathname and set up caller's user and group id */ @@ -55,8 +55,10 @@ PUBLIC int lookup() } /* Verify this is a null-terminated path. */ - if(user_path[len-1] != '\0') + if(user_path[len-1] != '\0') { + printf("mfs:lookup: didn't get null-terminated string.\n"); return EINVAL; + } caller_uid = fs_m_in.REQ_UID; caller_gid = fs_m_in.REQ_GID; diff --git a/servers/mfs/protect.c b/servers/mfs/protect.c index a2d1d609b..ecf80c246 100644 --- a/servers/mfs/protect.c +++ b/servers/mfs/protect.c @@ -50,6 +50,9 @@ printf("MFS(%d) get_inode by fs_chmod() failed\n", SELF_E); rip->i_update |= CTIME; rip->i_dirt = DIRTY; + /* Return full new mode to caller. */ + fs_m_out.RES_MODE = rip->i_mode; + put_inode(rip); return(OK); } @@ -94,7 +97,11 @@ printf("MFS(%d) get_inode by fs_chown() failed\n", SELF_E); rip->i_dirt = DIRTY; } + /* Update caller on current mode, as it may have changed. */ + fs_m_out.RES_MODE = rip->i_mode; + put_inode(rip); + return(r); } diff --git a/servers/vfs/device.c b/servers/vfs/device.c index 51d31e168..13c207b16 100644 --- a/servers/vfs/device.c +++ b/servers/vfs/device.c @@ -142,8 +142,8 @@ PUBLIC void dev_status(message *m) if(endpt == NONE) { printf("FS: proc with " "grant %d from %d not found (revive)\n", - st.m_source, - st.REP_IO_GRANT); + st.REP_IO_GRANT, + st.m_source); continue; } } diff --git a/servers/vfs/filedes.c b/servers/vfs/filedes.c index b070e517d..2503d2a62 100644 --- a/servers/vfs/filedes.c +++ b/servers/vfs/filedes.c @@ -3,13 +3,14 @@ * The entry points into this file are * get_fd: look for free file descriptor and free filp slots * get_filp: look up the filp entry for a given file descriptor - * find_filp: find a filp slot that points to a given inode + * find_filp: find a filp slot that points to a given vnode * inval_filp: invalidate a filp and associated fd's, only let close() * happen on it */ #include #include +#include #include "fs.h" #include "file.h" @@ -30,8 +31,6 @@ PUBLIC int get_fd(int start, mode_t bits, int *k, struct filp **fpt) register struct filp *f; register int i; - *k = -1; /* we need a way to tell if file desc found */ - /* Search the fproc fp_filp table for a free file descriptor. */ for (i = start; i < OPEN_MAX; i++) { if (fp->fp_filp[i] == NIL_FILP && !FD_ISSET(i, &fp->fp_filp_inuse)) { @@ -42,10 +41,11 @@ PUBLIC int get_fd(int start, mode_t bits, int *k, struct filp **fpt) } /* Check to see if a file descriptor has been found. */ - if (*k < 0) return(EMFILE); /* this is why we initialized k to -1 */ + if (i >= OPEN_MAX) return(EMFILE); /* Now that a file descriptor has been found, look for a free filp slot. */ for (f = &filp[0]; f < &filp[NR_FILPS]; f++) { + assert(f->filp_count >= 0); if (f->filp_count == 0) { f->filp_mode = bits; f->filp_pos = cvu64(0); @@ -92,7 +92,7 @@ int fild; /* file descriptor */ *===========================================================================*/ PUBLIC struct filp *find_filp(register struct vnode *vp, mode_t bits) { -/* Find a filp slot that refers to the inode 'rip' in a way as described +/* Find a filp slot that refers to the vnode 'vp' in a way as described * by the mode bit 'bits'. Used for determining whether somebody is still * interested in either end of a pipe. Also used when opening a FIFO to * find partners to share a filp field with (to shared the file position). @@ -103,6 +103,7 @@ PUBLIC struct filp *find_filp(register struct vnode *vp, mode_t bits) for (f = &filp[0]; f < &filp[NR_FILPS]; f++) { if (f->filp_count != 0 && f->filp_vno == vp && (f->filp_mode & bits)){ + assert(f->filp_count > 0); return(f); } } diff --git a/servers/vfs/glo.h b/servers/vfs/glo.h index 454425cd7..829353b37 100644 --- a/servers/vfs/glo.h +++ b/servers/vfs/glo.h @@ -24,7 +24,7 @@ EXTERN int who_p, who_e; /* caller's proc number, endpoint */ EXTERN int call_nr; /* system call number */ EXTERN message mount_m_in; /* the input message itself */ -EXTERN char user_fullpath[PATH_MAX]; /* storage for user path name */ +EXTERN char user_fullpath[PATH_MAX+1]; /* storage for user path name */ EXTERN short cum_path_processed; /* number of characters processed */ /* The following variables are used for returning results to the caller. */ diff --git a/servers/vfs/main.c b/servers/vfs/main.c index 49a8233e7..47018444c 100644 --- a/servers/vfs/main.c +++ b/servers/vfs/main.c @@ -133,6 +133,8 @@ PUBLIC int main() panic(__FILE__, "check_vrefs failed at line", __LINE__); } #endif + + } return(OK); /* shouldn't come here */ } @@ -170,9 +172,10 @@ PRIVATE void get_work() } for(;;) { + int r; /* Normal case. No one to revive. */ - if (receive(ANY, &m_in) != OK) - panic(__FILE__,"fs receive error", NO_NUM); + if ((r=receive(ANY, &m_in)) != OK) + panic(__FILE__,"fs receive error", r); who_e = m_in.m_source; who_p = _ENDPOINT_P(who_e); diff --git a/servers/vfs/mount.c b/servers/vfs/mount.c index 6eb207027..cfa347665 100644 --- a/servers/vfs/mount.c +++ b/servers/vfs/mount.c @@ -491,7 +491,6 @@ Dev_t dev; } if (count > 1) { - printf("VFSunmount: %d filesystem is busy count: %d\n", dev, count); return(EBUSY); /* can't umount a busy file system */ } diff --git a/servers/vfs/open.c b/servers/vfs/open.c index ae8756299..42a05622e 100644 --- a/servers/vfs/open.c +++ b/servers/vfs/open.c @@ -26,6 +26,7 @@ #include "lock.h" #include "param.h" #include +#include #include #include "vnode.h" @@ -117,10 +118,6 @@ PRIVATE int common_open(register int oflags, mode_t omode) vp= NULL; -#if 0 - printf("common_open: for '%s'\n", user_fullpath); -#endif - /* Fill in lookup request fields */ Xlookup_req.path = user_fullpath; Xlookup_req.lastc = Xlastc; @@ -146,11 +143,18 @@ PRIVATE int common_open(register int oflags, mode_t omode) { if (pathrem == NULL) panic(__FILE__, "no pathrem", NO_NUM); - if (strchr(pathrem, '/') == 0) + + /* If any path remains, but no '/', O_CREAT can continue. + * If no path remains, a null filename was provided so ENOENT + * remains. + */ + if(*pathrem) { + if (strchr(pathrem, '/') == 0) r= OK; - else - { + else + { printf("common_open: / in pathrem\n"); + } } } @@ -278,8 +282,6 @@ PRIVATE int common_open(register int oflags, mode_t omode) break; case I_NAMED_PIPE: - printf("common_open: setting I_PIPE, inode %d on dev 0x%x\n", - vp->v_inode_nr, vp->v_dev); vp->v_pipe = I_PIPE; vp->v_isfifo= TRUE; oflags |= O_APPEND; /* force append mode */ @@ -291,6 +293,7 @@ PRIVATE int common_open(register int oflags, mode_t omode) * file position will be automatically shared. */ b = (bits & R_BIT ? R_BIT : W_BIT); + assert(fil_ptr->filp_count == 1); fil_ptr->filp_count = 0; /* don't find self */ if ((filp2 = find_filp(vp, b)) != NIL_FILP) { /* Co-reader or writer found. Use it.*/ @@ -428,15 +431,10 @@ struct vnode **vpp; break; case I_NAMED_PIPE: - printf("x_open (fifo): reference count %d, fd %d\n", - vp->v_ref_count, vp->v_fs_count); if (vp->v_ref_count == 1) { - printf("x_open (fifo): first reference, size %u\n", - vp->v_size); if (vp->v_size != 0) { - printf("x_open (fifo): clearing\n"); r= truncate_vn(vp, 0); if (r != OK) { @@ -465,8 +463,6 @@ PRIVATE int pipe_open(register struct vnode *vp, register mode_t bits, * processes hanging on the pipe. */ - printf("pipe_open: setting I_PIPE, inode %d on dev 0x%x\n", - vp->v_inode_nr, vp->v_dev); vp->v_pipe = I_PIPE; if((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) { @@ -735,6 +731,12 @@ int fd_nr; /* If a write has been done, the inode is already marked as DIRTY. */ if (--rfilp->filp_count == 0) { + if (vp->v_pipe == I_PIPE) { + /* Last reader or writer is going. Tell MFS about latest + * pipe size. + */ + truncate_vn(vp, vp->v_size); + } if (vp->v_pipe == I_PIPE && vp->v_ref_count > 1) { /* Save the file position in the v-node in case needed later. * The read and write positions are saved separately. diff --git a/servers/vfs/path.c b/servers/vfs/path.c index fa6051f97..c005911d6 100644 --- a/servers/vfs/path.c +++ b/servers/vfs/path.c @@ -43,6 +43,7 @@ node_details_t *node; /* Empty (start) path? */ if (fullpath[0] == '\0') { + node->inode_nr = 0; return ENOENT; } @@ -178,6 +179,8 @@ char **pathrem; /* Empty (start) path? */ if (fullpath[0] == '\0') { + node->inode_nr = 0; + *pathrem = fullpath; return ENOENT; } @@ -314,7 +317,7 @@ struct vnode **vpp; if (res.inode_nr == 0) { printf("lookup_vp: lookup returned no inode\n"); - printf("lookup_res = %d, last = '%s'\n", + printf("lookup_res = %d, last = '%s'\n\n", lookup_res, lookup_req->lastc); *vpp= NULL; return lookup_res; @@ -386,7 +389,7 @@ char **pathrem; if (res.inode_nr == 0) { printf("Xlookup_vp: lookup returned no inode\n"); - printf("lookup_res = %d, last = '%s'\n", + printf("lookup_res = %d, last = '%s'\n\n", lookup_res, lookup_req->lastc); *vpp= NULL; return lookup_res; diff --git a/servers/vfs/protect.c b/servers/vfs/protect.c index 093bc2200..3ac498b72 100644 --- a/servers/vfs/protect.c +++ b/servers/vfs/protect.c @@ -34,7 +34,8 @@ PUBLIC int do_chmod() struct chmod_req req; struct lookup_req lookup_req; struct node_details res; - int r; + struct vnode *vp; + int r, ch_mode; if (call_nr == CHMOD) { /* Perform the chmod(name, mode) system call. */ @@ -58,13 +59,21 @@ PUBLIC int do_chmod() } else panic(__FILE__, "do_chmod called with strange call_nr", call_nr); + /* Find vnode, if it's in use. */ + vp = find_vnode(req.fs_e, req.inode_nr); + /* Fill in request message fields.*/ req.uid = fp->fp_effuid; req.gid = fp->fp_effgid; req.rmode = m_in.mode; /* Issue request */ - return req_chmod(&req); + if((r = req_chmod(&req, &ch_mode)) != OK) return r; + + if(vp != NIL_VNODE) + vp->v_mode = ch_mode; + + return OK; } /*===========================================================================* @@ -78,7 +87,8 @@ PUBLIC int do_chown() struct chown_req req; struct lookup_req lookup_req; struct node_details res; - int r; + struct vnode *vp; + int r, ch_mode; if (call_nr == CHOWN) { /* Perform the chmod(name, mode) system call. */ @@ -102,6 +112,9 @@ PUBLIC int do_chown() } else panic(__FILE__, "do_chmod called with strange call_nr", call_nr); + /* Find vnode, if it's in use. */ + vp = find_vnode(req.fs_e, req.inode_nr); + /* Fill in request message fields.*/ req.uid = fp->fp_effuid; req.gid = fp->fp_effgid; @@ -109,7 +122,15 @@ PUBLIC int do_chown() req.newgid = m_in.group; /* Issue request */ - return req_chown(&req); + r = req_chown(&req, &ch_mode); + + if(r == OK && vp) { + vp->v_uid = m_in.owner; + vp->v_gid = m_in.group; + vp->v_mode = ch_mode; + } + + return r; } @@ -207,7 +228,9 @@ PUBLIC int forbidden(struct vnode *vp, mode_t access_desired) /* If access desired is not a subset of what is allowed, it is refused. */ r = OK; - if ((perm_bits | access_desired) != perm_bits) r = EACCES; + if ((perm_bits | access_desired) != perm_bits) { + r = EACCES; + } /* Check to see if someone is trying to write on a file system that is * mounted read-only. diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h index bfcca929f..1248f5f18 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -133,7 +133,8 @@ _PROTOTYPE( int do_getdents, (void) ); _PROTOTYPE( int read_write, (int rw_flag) ); /* request.c */ -_PROTOTYPE( int req_getnode, (node_req_t *req, node_details_t *res) ); +#define req_getnode(req, res) req_getnode_f(__FILE__, __LINE__, (req), (res)) +_PROTOTYPE( int req_getnode_f, (char *file, int line, node_req_t *req, node_details_t *res) ); _PROTOTYPE( int req_putnode, (int fs_e, ino_t inode_nr, int count) ); _PROTOTYPE( int req_open, (open_req_t *req, node_details_t *res) ); _PROTOTYPE( int req_create, (int fs_e, ino_t inode_nr, int omode, @@ -144,8 +145,8 @@ _PROTOTYPE( int req_pipe, (pipe_req_t *req, node_details_t *res) ); _PROTOTYPE( int req_clone_opcl, (clone_opcl_req_t *req, node_details_t *res) ); _PROTOTYPE( int req_ftrunc, (ftrunc_req_t *req) ); -_PROTOTYPE( int req_chown, (chown_req_t *req) ); -_PROTOTYPE( int req_chmod, (chmod_req_t *req) ); +_PROTOTYPE( int req_chown, (chown_req_t *req, int *mode) ); +_PROTOTYPE( int req_chmod, (chmod_req_t *req, int *mode) ); _PROTOTYPE( int req_access, (access_req_t *req) ); _PROTOTYPE( int req_mknod, (mknod_req_t *req) ); _PROTOTYPE( int req_mkdir, (mkdir_req_t *req) ); @@ -240,3 +241,4 @@ _PROTOTYPE( void fs_expire_timers, (clock_t now) ); _PROTOTYPE( void fs_cancel_timer, (timer_t *tp) ); _PROTOTYPE( void fs_init_timer, (timer_t *tp) ); + diff --git a/servers/vfs/read.c b/servers/vfs/read.c index d142d33dd..54ef44cba 100644 --- a/servers/vfs/read.c +++ b/servers/vfs/read.c @@ -21,6 +21,7 @@ #include "fproc.h" #include "param.h" #include +#include #include #include "vnode.h" @@ -45,7 +46,7 @@ int rw_flag; /* READING or WRITING */ /* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */ register struct filp *f; register struct vnode *vp; - off_t bytes_left, f_size; + off_t bytes_left; u64_t position; unsigned int off, cum_io; int op, oflags, r, chunk, usr, seg, block_spec, char_spec; @@ -97,7 +98,6 @@ int rw_flag; /* READING or WRITING */ oflags = f->filp_flags; vp = f->filp_vno; - f_size = vp->v_size; r = OK; if (vp->v_pipe == I_PIPE) { @@ -119,7 +119,6 @@ int rw_flag; /* READING or WRITING */ } if ((block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0))) { - f_size = ULONG_MAX; if (vp->v_sdev == NO_DEV) panic(__FILE__,"read_write tries to read from " " block device NO_DEV", NO_NUM); @@ -155,11 +154,11 @@ int rw_flag; /* READING or WRITING */ position = res.new_pos; cum_io += res.cum_io; } - /* Regular files */ + /* Regular files (and pipes) */ else { if (rw_flag == WRITING && block_spec == 0) { /* Check for O_APPEND flag. */ - if (oflags & O_APPEND) position = cvul64(f_size); + if (oflags & O_APPEND) position = cvul64(vp->v_size); /* Check in advance to see if file will grow too big. */ if (cmp64ul(position, vp->v_vmnt->m_max_file_size - m_in.nbytes) > 0) @@ -175,8 +174,9 @@ int rw_flag; /* READING or WRITING */ } if (partial_cnt > 0) { - /* So taht we don't need to deal with partial count - * in the FS process */ + /* So that we don't need to deal with partial count + * in the FS process. + */ m_in.nbytes = MIN(m_in.nbytes, partial_cnt); partial_pipe = 1; } @@ -192,11 +192,17 @@ int rw_flag; /* READING or WRITING */ req.user_addr = m_in.buffer; req.inode_index = vp->v_index; - if (vp->v_isfifo) - { - printf("read_write: %s for FIFO @ %u size %u\n", - (rw_flag == READING) ? "read" : "write", - ex64lo(position), m_in.nbytes); + /* Truncate read request at size (mustn't do this for special files). */ + if((rw_flag == READING) && + cmp64ul(add64ul(position, req.num_of_bytes), vp->v_size) > 0) { + /* Position always should fit in an off_t (LONG_MAX). */ + off_t pos32; + assert(cmp64ul(position, LONG_MAX) <= 0); + pos32 = cv64ul(position); + assert(pos32 >= 0); + assert(pos32 <= LONG_MAX); + req.num_of_bytes = vp->v_size - pos32; + assert(req.num_of_bytes >= 0); } /* Issue request */ @@ -215,7 +221,7 @@ int rw_flag; /* READING or WRITING */ /* On write, update file size and access time. */ if (rw_flag == WRITING) { if (regular || mode_word == I_DIRECTORY) { - if (cmp64ul(position, f_size) > 0) + if (cmp64ul(position, vp->v_size) > 0) { if (ex64hi(position) != 0) { diff --git a/servers/vfs/request.c b/servers/vfs/request.c index 4f620911d..b4ca2810e 100644 --- a/servers/vfs/request.c +++ b/servers/vfs/request.c @@ -28,12 +28,16 @@ #include "vnode.h" #include "param.h" -FORWARD _PROTOTYPE(int fs_sendrec, (endpoint_t fs_e, message *reqm)); +FORWARD _PROTOTYPE(int fs_sendrec_f, (char *file, int line, endpoint_t fs_e, message *reqm)); + +#define fs_sendrec(e, m) fs_sendrec_f(__FILE__, __LINE__, (e), (m)) /*===========================================================================* * req_getnode * *===========================================================================*/ -PUBLIC int req_getnode(req, res) +PUBLIC int req_getnode_f(file, line, req, res) +char *file; +int line; node_req_t *req; node_details_t *res; { @@ -278,10 +282,12 @@ ftrunc_req_t *req; /*===========================================================================* * req_chmod * *===========================================================================*/ -PUBLIC int req_chmod(req) +PUBLIC int req_chmod(req, ch_mode) chmod_req_t *req; +int *ch_mode; { message m; + int r; /* Fill in request message */ m.m_type = REQ_CHMOD; @@ -291,17 +297,24 @@ chmod_req_t *req; m.REQ_GID = req->gid; /* Send/rec request */ - return fs_sendrec(req->fs_e, &m); + r = fs_sendrec(req->fs_e, &m); + + /* Copy back actual mode. */ + if(ch_mode) *ch_mode = m.RES_MODE; + + return r; } /*===========================================================================* * req_chown * *===========================================================================*/ -PUBLIC int req_chown(req) +PUBLIC int req_chown(req, ch_mode) chown_req_t *req; +int *ch_mode; { message m; + int r; /* Fill in request message */ m.m_type = REQ_CHOWN; @@ -312,7 +325,12 @@ chown_req_t *req; m.REQ_NEW_GID = req->newgid; /* Send/rec request */ - return fs_sendrec(req->fs_e, &m); + r = fs_sendrec(req->fs_e, &m); + + /* Return new mode to caller. */ + if(ch_mode) *ch_mode = m.RES_MODE; + + return r; } @@ -955,7 +973,7 @@ _t *res; /*===========================================================================* * fs_sendrec * *===========================================================================*/ -PRIVATE int fs_sendrec(endpoint_t fs_e, message *reqm) +PRIVATE int fs_sendrec_f(char *file, int line, endpoint_t fs_e, message *reqm) { /* This is the low level function that sends requests to FS processes. * It also handles driver recovery mechanism and reissuing the @@ -964,7 +982,7 @@ PRIVATE int fs_sendrec(endpoint_t fs_e, message *reqm) int r, old_driver_e, new_driver_e; message origm, m; struct vmnt *vmp; - + /* Make a copy of the request so that we can load it back in * case of a dead driver */ origm = *reqm; @@ -972,8 +990,8 @@ PRIVATE int fs_sendrec(endpoint_t fs_e, message *reqm) for (;;) { /* Do the actual send, receive */ if (OK != (r=sendrec(fs_e, reqm))) { - printf("VFS: error sending message. FS_e: %d req_nr: %d err: %d\n", - fs_e, reqm->m_type, r); + printf("VFS:fs_sendrec:%s:%d: error sending message. FS_e: %d req_nr: %d err: %d\n", + file, line, fs_e, reqm->m_type, r); } if(r == OK) { @@ -984,9 +1002,9 @@ PRIVATE int fs_sendrec(endpoint_t fs_e, message *reqm) /* Dead driver */ if (r == EDEADSRCDST || r == EDSTDIED || r == ESRCDIED) { old_driver_e = NONE; - /* Find old driver enpoint */ + /* Find old driver by endpoint */ for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) { - if (vmp->m_fs_e == reqm->m_source) { /* found FS */ + if (vmp->m_fs_e == fs_e) { /* found FS */ old_driver_e = vmp->m_driver_e; dmap_unmap_by_endpt(old_driver_e); /* unmap driver */ break; @@ -994,10 +1012,8 @@ PRIVATE int fs_sendrec(endpoint_t fs_e, message *reqm) } /* No FS ?? */ - if (old_driver_e == NONE) { - panic(__FILE__, "VFSdead_driver: couldn't find FS\n", - old_driver_e); - } + if (old_driver_e == NONE) + panic(__FILE__, "VFSdead_driver: couldn't find FS\n", fs_e); /* Wait for a new driver. */ for (;;) { diff --git a/servers/vfs/stadir.c b/servers/vfs/stadir.c index 2b90d2a81..544a315c8 100644 --- a/servers/vfs/stadir.c +++ b/servers/vfs/stadir.c @@ -141,7 +141,14 @@ int len; /* length of the directory name string */ put_vnode(vp); return ENOTDIR; } - + + /* Access check */ + r = forbidden(vp, X_BIT); + if (r != OK) { + put_vnode(vp); + return r; + } + return change_into(iip, vp); } diff --git a/servers/vfs/utility.c b/servers/vfs/utility.c index b5410c3c5..97f12a3d7 100644 --- a/servers/vfs/utility.c +++ b/servers/vfs/utility.c @@ -17,6 +17,7 @@ #include "file.h" #include "fproc.h" #include "param.h" +#include "vmnt.h" PRIVATE int panicking; /* inhibits recursive panics during sync */ @@ -35,6 +36,11 @@ int flag; /* M3 means path may be in message */ register char *rpu, *rpm; int r; + if (len > PATH_MAX) { + err_code = ENAMETOOLONG; + return(EGENERIC); + } + if(len >= sizeof(user_fullpath)) { panic(__FILE__, "fetch_name: len too much for user_fullpath", len); } @@ -42,11 +48,7 @@ int flag; /* M3 means path may be in message */ /* Check name length for validity. */ if (len <= 0) { err_code = EINVAL; - return(EGENERIC); - } - - if (len > PATH_MAX) { - err_code = ENAMETOOLONG; + printf("vfs: fetch_name: len %d?\n", len); return(EGENERIC); } @@ -100,7 +102,7 @@ int num; /* number to go with it */ if (panicking) return; /* do not panic during a sync */ panicking = TRUE; /* prevent another panic during the sync */ - printf("FS panic (%s): %s ", who, mess); + printf("VFS panic (%s): %s ", who, mess); if (num != NO_NUM) printf("%d",num); (void) do_sync(); /* flush everything to the disk */ sys_exit(SELF); @@ -148,4 +150,3 @@ PUBLIC time_t clock_time() return( (time_t) (boottime + (uptime/HZ))); } -