BOOK.TXT
上传用户:jnzhq888
上传日期:2007-01-18
资源大小:51694k
文件大小:1020k
- 17269 /*===========================================================================*
- 17270 * read_header *
- 17271 *===========================================================================*/
- 17272 PRIVATE int read_header(fd, ft, text_bytes, data_bytes, bss_bytes,
- 17273 tot_bytes, sym_bytes, sc, pc)
- 17274 int fd; /* file descriptor for reading exec file */
- 17275 int *ft; /* place to return ft number */
- 17276 vir_bytes *text_bytes; /* place to return text size */
- 17277 vir_bytes *data_bytes; /* place to return initialized data size */
- 17278 vir_bytes *bss_bytes; /* place to return bss size */
- 17279 phys_bytes *tot_bytes; /* place to return total size */
- 17280 long *sym_bytes; /* place to return symbol table size */
- 17281 vir_clicks sc; /* stack size in clicks */
- 17282 vir_bytes *pc; /* program entry point (initial PC) */
- 17283 {
- 17284 /* Read the header and extract the text, data, bss and total sizes from it. */
- 17285
- 17286 int m, ct;
- 17287 vir_clicks tc, dc, s_vir, dvir;
- 17288 phys_clicks totc;
- 17289 struct exec hdr; /* a.out header is read in here */
- 17290
- 17291 /* Read the header and check the magic number. The standard MINIX header
- 17292 * is defined in <a.out.h>. It consists of 8 chars followed by 6 longs.
- 17293 * Then come 4 more longs that are not used here.
- 17294 * Byte 0: magic number 0x01
- 17295 * Byte 1: magic number 0x03
- 17296 * Byte 2: normal = 0x10 (not checked, 0 is OK), separate I/D = 0x20
- 17297 * Byte 3: CPU type, Intel 16 bit = 0x04, Intel 32 bit = 0x10,
- 17298 * Motorola = 0x0B, Sun SPARC = 0x17
- 17299 * Byte 4: Header length = 0x20
- 17300 * Bytes 5-7 are not used.
- 17301 *
- 17302 * Now come the 6 longs
- 17303 * Bytes 8-11: size of text segments in bytes
- 17304 * Bytes 12-15: size of initialized data segment in bytes
- 17305 * Bytes 16-19: size of bss in bytes
- 17306 * Bytes 20-23: program entry point
- 17307 * Bytes 24-27: total memory allocated to program (text, data + stack)
- 17308 * Bytes 28-31: size of symbol table in bytes
- 17309 * The longs are represented in a machine dependent order,
- 17310 * little-endian on the 8088, big-endian on the 68000.
- 17311 * The header is followed directly by the text and data segments, and the
- 17312 * symbol table (if any). The sizes are given in the header. Only the
- 17313 * text and data segments are copied into memory by exec. The header is
- 17314 * used here only. The symbol table is for the benefit of a debugger and
- 17315 * is ignored here.
- 17316 */
- 17317
- 17318 if (read(fd, (char *) &hdr, A_MINHDR) != A_MINHDR) return(ENOEXEC);
- 17319
- 17320 /* Check magic number, cpu type, and flags. */
- 17321 if (BADMAG(hdr)) return(ENOEXEC);
- 17322 #if (CHIP == INTEL && _WORD_SIZE == 2)
- 17323 if (hdr.a_cpu != A_I8086) return(ENOEXEC);
- 17324 #endif
- 17325 #if (CHIP == INTEL && _WORD_SIZE == 4)
- 17326 if (hdr.a_cpu != A_I80386) return(ENOEXEC);
- 17327 #endif
- 17328 if ((hdr.a_flags & ~(A_NSYM | A_EXEC | A_SEP)) != 0) return(ENOEXEC);
- 17329
- 17330 *ft = ( (hdr.a_flags & A_SEP) ? SEPARATE : 0); /* separate I & D or not */
- 17331
- 17332 /* Get text and data sizes. */
- 17333 *text_bytes = (vir_bytes) hdr.a_text; /* text size in bytes */
- 17334 *data_bytes = (vir_bytes) hdr.a_data; /* data size in bytes */
- 17335 *bss_bytes = (vir_bytes) hdr.a_bss; /* bss size in bytes */
- 17336 *tot_bytes = hdr.a_total; /* total bytes to allocate for prog */
- 17337 *sym_bytes = hdr.a_syms; /* symbol table size in bytes */
- 17338 if (*tot_bytes == 0) return(ENOEXEC);
- 17339
- 17340 if (*ft != SEPARATE) {
- 17341
- 17342 /* If I & D space is not separated, it is all considered data. Text=0*/
- 17343 *data_bytes += *text_bytes;
- 17344 *text_bytes = 0;
- 17345
- 17346 }
- 17347 *pc = hdr.a_entry; /* initial address to start execution */
- 17348
- 17349 /* Check to see if segment sizes are feasible. */
- 17350 tc = ((unsigned long) *text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
- 17351 dc = (*data_bytes + *bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
- 17352 totc = (*tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
- 17353 if (dc >= totc) return(ENOEXEC); /* stack must be at least 1 click */
- 17354 dvir = (*ft == SEPARATE ? 0 : tc);
- 17355 s_vir = dvir + (totc - sc);
- 17356 m = size_ok(*ft, tc, dc, sc, dvir, s_vir);
- 17357 ct = hdr.a_hdrlen & BYTE; /* header length */
- 17358 if (ct > A_MINHDR) lseek(fd, (off_t) ct, SEEK_SET); /* skip unused hdr */
- 17359 return(m);
- 17360 }
-
-
- 17363 /*===========================================================================*
- 17364 * new_mem *
- 17365 *===========================================================================*/
- 17366 PRIVATE int new_mem(sh_mp, text_bytes, data_bytes,bss_bytes,stk_bytes,tot_bytes)
- 17367 struct mproc *sh_mp; /* text can be shared with this process */
- 17368 vir_bytes text_bytes; /* text segment size in bytes */
- 17369 vir_bytes data_bytes; /* size of initialized data in bytes */
- 17370 vir_bytes bss_bytes; /* size of bss in bytes */
- 17371 vir_bytes stk_bytes; /* size of initial stack segment in bytes */
- 17372 phys_bytes tot_bytes; /* total memory to allocate, including gap */
- 17373 {
- 17374 /* Allocate new memory and release the old memory. Change the map and report
- 17375 * the new map to the kernel. Zero the new core image's bss, gap and stack.
- 17376 */
- 17377
- 17378 register struct mproc *rmp;
- 17379 vir_clicks text_clicks, data_clicks, gap_clicks, stack_clicks, tot_clicks;
- 17380 phys_clicks new_base;
- 17381
- 17382 static char zero[1024]; /* used to zero bss */
- 17383 phys_bytes bytes, base, count, bss_offset;
- 17384
- 17385 /* No need to allocate text if it can be shared. */
- 17386 if (sh_mp != NULL) text_bytes = 0;
- 17387
- 17388 /* Acquire the new memory. Each of the 4 parts: text, (data+bss), gap,
- 17389 * and stack occupies an integral number of clicks, starting at click
- 17390 * boundary. The data and bss parts are run together with no space.
- 17391 */
- 17392
- 17393 text_clicks = ((unsigned long) text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
- 17394 data_clicks = (data_bytes + bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
- 17395 stack_clicks = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
- 17396 tot_clicks = (tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
- 17397 gap_clicks = tot_clicks - data_clicks - stack_clicks;
- 17398 if ( (int) gap_clicks < 0) return(ENOMEM);
- 17399
- 17400 /* Check to see if there is a hole big enough. If so, we can risk first
- 17401 * releasing the old core image before allocating the new one, since we
- 17402 * know it will succeed. If there is not enough, return failure.
- 17403 */
- 17404 if (text_clicks + tot_clicks > max_hole()) return(EAGAIN);
- 17405
- 17406 /* There is enough memory for the new core image. Release the old one. */
- 17407 rmp = mp;
- 17408
- 17409 if (find_share(rmp, rmp->mp_ino, rmp->mp_dev, rmp->mp_ctime) == NULL) {
- 17410 /* No other process shares the text segment, so free it. */
- 17411 free_mem(rmp->mp_seg[T].mem_phys, rmp->mp_seg[T].mem_len);
- 17412 }
- 17413 /* Free the data and stack segments. */
- 17414 free_mem(rmp->mp_seg[D].mem_phys,
- 17415 rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len - rmp->mp_seg[D].mem_vir);
- 17416
- 17417 /* We have now passed the point of no return. The old core image has been
- 17418 * forever lost. The call must go through now. Set up and report new map.
- 17419 */
- 17420 new_base = alloc_mem(text_clicks + tot_clicks); /* new core image */
- 17421 if (new_base == NO_MEM) panic("MM hole list is inconsistent", NO_NUM);
- 17422
- 17423 if (sh_mp != NULL) {
- 17424 /* Share the text segment. */
- 17425 rmp->mp_seg[T] = sh_mp->mp_seg[T];
- 17426 } else {
- 17427 rmp->mp_seg[T].mem_phys = new_base;
- 17428 rmp->mp_seg[T].mem_vir = 0;
- 17429 rmp->mp_seg[T].mem_len = text_clicks;
- 17430 }
- 17431 rmp->mp_seg[D].mem_phys = new_base + text_clicks;
- 17432 rmp->mp_seg[D].mem_vir = 0;
- 17433 rmp->mp_seg[D].mem_len = data_clicks;
- 17434 rmp->mp_seg[S].mem_phys = rmp->mp_seg[D].mem_phys + data_clicks + gap_clicks;
- 17435 rmp->mp_seg[S].mem_vir = rmp->mp_seg[D].mem_vir + data_clicks + gap_clicks;
- 17436 rmp->mp_seg[S].mem_len = stack_clicks;
- 17437
- 17438
- 17439 sys_newmap(who, rmp->mp_seg); /* report new map to the kernel */
- 17440
- 17441 /* Zero the bss, gap, and stack segment. */
- 17442 bytes = (phys_bytes)(data_clicks + gap_clicks + stack_clicks) << CLICK_SHIFT;
- 17443 base = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT;
- 17444 bss_offset = (data_bytes >> CLICK_SHIFT) << CLICK_SHIFT;
- 17445 base += bss_offset;
- 17446 bytes -= bss_offset;
- 17447
- 17448 while (bytes > 0) {
- 17449 count = MIN(bytes, (phys_bytes) sizeof(zero));
- 17450 if (sys_copy(MM_PROC_NR, D, (phys_bytes) zero,
- 17451 ABS, 0, base, count) != OK) {
- 17452 panic("new_mem can't zero", NO_NUM);
- 17453 }
- 17454 base += count;
- 17455 bytes -= count;
- 17456 }
- 17457
- 17458 return(OK);
- 17459 }
-
-
- 17462 /*===========================================================================*
- 17463 * patch_ptr *
- 17464 *===========================================================================*/
- 17465 PRIVATE void patch_ptr(stack, base)
- 17466 char stack[ARG_MAX]; /* pointer to stack image within MM */
- 17467 vir_bytes base; /* virtual address of stack base inside user */
- 17468 {
- 17469 /* When doing an exec(name, argv, envp) call, the user builds up a stack
- 17470 * image with arg and env pointers relative to the start of the stack. Now
- 17471 * these pointers must be relocated, since the stack is not positioned at
- 17472 * address 0 in the user's address space.
- 17473 */
- 17474
- 17475 char **ap, flag;
- 17476 vir_bytes v;
- 17477
- 17478 flag = 0; /* counts number of 0-pointers seen */
- 17479 ap = (char **) stack; /* points initially to 'nargs' */
- 17480 ap++; /* now points to argv[0] */
- 17481 while (flag < 2) {
- 17482 if (ap >= (char **) &stack[ARG_MAX]) return; /* too bad */
- 17483 if (*ap != NIL_PTR) {
- 17484 v = (vir_bytes) *ap; /* v is relative pointer */
- 17485 v += base; /* relocate it */
- 17486 *ap = (char *) v; /* put it back */
- 17487 } else {
- 17488 flag++;
- 17489 }
- 17490 ap++;
- 17491 }
- 17492 }
-
-
- 17495 /*===========================================================================*
- 17496 * load_seg *
- 17497 *===========================================================================*/
- 17498 PRIVATE void load_seg(fd, seg, seg_bytes)
- 17499 int fd; /* file descriptor to read from */
- 17500 int seg; /* T or D */
- 17501 vir_bytes seg_bytes; /* how big is the segment */
- 17502 {
- 17503 /* Read in text or data from the exec file and copy to the new core image.
- 17504 * This procedure is a little bit tricky. The logical way to load a segment
- 17505 * would be to read it block by block and copy each block to the user space
- 17506 * one at a time. This is too slow, so we do something dirty here, namely
- 17507 * send the user space and virtual address to the file system in the upper
- 17508 * 10 bits of the file descriptor, and pass it the user virtual address
- 17509 * instead of a MM address. The file system extracts these parameters when
- 17510 * gets a read call from the memory manager, which is the only process that
- 17511 * is permitted to use this trick. The file system then copies the whole
- 17512 * segment directly to user space, bypassing MM completely.
- 17513 */
- 17514
- 17515 int new_fd, bytes;
- 17516 char *ubuf_ptr;
- 17517
- 17518 new_fd = (who << 8) | (seg << 6) | fd;
- 17519 ubuf_ptr = (char *) ((vir_bytes)mp->mp_seg[seg].mem_vir << CLICK_SHIFT);
- 17520 while (seg_bytes != 0) {
- 17521 bytes = (INT_MAX / BLOCK_SIZE) * BLOCK_SIZE;
- 17522 if (seg_bytes < bytes)
- 17523 bytes = (int)seg_bytes;
- 17524 if (read(new_fd, ubuf_ptr, bytes) != bytes)
- 17525 break; /* error */
- 17526 ubuf_ptr += bytes;
- 17527 seg_bytes -= bytes;
- 17528 }
- 17529 }
-
-
- 17532 /*===========================================================================*
- 17533 * find_share *
- 17534 *===========================================================================*/
- 17535 PUBLIC struct mproc *find_share(mp_ign, ino, dev, ctime)
- 17536 struct mproc *mp_ign; /* process that should not be looked at */
- 17537 ino_t ino; /* parameters that uniquely identify a file */
- 17538 dev_t dev;
- 17539 time_t ctime;
- 17540 {
- 17541 /* Look for a process that is the file <ino, dev, ctime> in execution. Don't
- 17542 * accidentally "find" mp_ign, because it is the process on whose behalf this
- 17543 * call is made.
- 17544 */
- 17545 struct mproc *sh_mp;
- 17546
- 17547 for (sh_mp = &mproc[INIT_PROC_NR]; sh_mp < &mproc[NR_PROCS]; sh_mp++) {
- 17548 if ((sh_mp->mp_flags & (IN_USE | HANGING | SEPARATE))
- 17549 != (IN_USE | SEPARATE)) continue;
- 17550 if (sh_mp == mp_ign) continue;
- 17551 if (sh_mp->mp_ino != ino) continue;
- 17552 if (sh_mp->mp_dev != dev) continue;
- 17553 if (sh_mp->mp_ctime != ctime) continue;
- 17554 return sh_mp;
- 17555 }
- 17556 return(NULL);
- 17557 }
-
-
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/mm/break.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 17600 /* The MINIX model of memory allocation reserves a fixed amount of memory for
- 17601 * the combined text, data, and stack segments. The amount used for a child
- 17602 * process created by FORK is the same as the parent had. If the child does
- 17603 * an EXEC later, the new size is taken from the header of the file EXEC'ed.
- 17604 *
- 17605 * The layout in memory consists of the text segment, followed by the data
- 17606 * segment, followed by a gap (unused memory), followed by the stack segment.
- 17607 * The data segment grows upward and the stack grows downward, so each can
- 17608 * take memory from the gap. If they meet, the process must be killed. The
- 17609 * procedures in this file deal with the growth of the data and stack segments.
- 17610 *
- 17611 * The entry points into this file are:
- 17612 * do_brk: BRK/SBRK system calls to grow or shrink the data segment
- 17613 * adjust: see if a proposed segment adjustment is allowed
- 17614 * size_ok: see if the segment sizes are feasible
- 17615 */
- 17616
- 17617 #include "mm.h"
- 17618 #include <signal.h>
- 17619 #include "mproc.h"
- 17620 #include "param.h"
- 17621
- 17622 #define DATA_CHANGED 1 /* flag value when data segment size changed */
- 17623 #define STACK_CHANGED 2 /* flag value when stack size changed */
- 17624
- 17625 /*===========================================================================*
- 17626 * do_brk *
- 17627 *===========================================================================*/
- 17628 PUBLIC int do_brk()
- 17629 {
- 17630 /* Perform the brk(addr) system call.
- 17631 *
- 17632 * The call is complicated by the fact that on some machines (e.g., 8088),
- 17633 * the stack pointer can grow beyond the base of the stack segment without
- 17634 * anybody noticing it.
- 17635 * The parameter, 'addr' is the new virtual address in D space.
- 17636 */
- 17637
- 17638 register struct mproc *rmp;
- 17639 int r;
- 17640 vir_bytes v, new_sp;
- 17641 vir_clicks new_clicks;
- 17642
- 17643 rmp = mp;
- 17644 v = (vir_bytes) addr;
- 17645 new_clicks = (vir_clicks) ( ((long) v + CLICK_SIZE - 1) >> CLICK_SHIFT);
- 17646 if (new_clicks < rmp->mp_seg[D].mem_vir) {
- 17647 res_ptr = (char *) -1;
- 17648 return(ENOMEM);
- 17649 }
- 17650 new_clicks -= rmp->mp_seg[D].mem_vir;
- 17651 sys_getsp(who, &new_sp); /* ask kernel for current sp value */
- 17652 r = adjust(rmp, new_clicks, new_sp);
- 17653 res_ptr = (r == OK ? addr : (char *) -1);
- 17654 return(r); /* return new address or -1 */
- 17655 }
-
-
- 17658 /*===========================================================================*
- 17659 * adjust *
- 17660 *===========================================================================*/
- 17661 PUBLIC int adjust(rmp, data_clicks, sp)
- 17662 register struct mproc *rmp; /* whose memory is being adjusted? */
- 17663 vir_clicks data_clicks; /* how big is data segment to become? */
- 17664 vir_bytes sp; /* new value of sp */
- 17665 {
- 17666 /* See if data and stack segments can coexist, adjusting them if need be.
- 17667 * Memory is never allocated or freed. Instead it is added or removed from the
- 17668 * gap between data segment and stack segment. If the gap size becomes
- 17669 * negative, the adjustment of data or stack fails and ENOMEM is returned.
- 17670 */
- 17671
- 17672 register struct mem_map *mem_sp, *mem_dp;
- 17673 vir_clicks sp_click, gap_base, lower, old_clicks;
- 17674 int changed, r, ft;
- 17675 long base_of_stack, delta; /* longs avoid certain problems */
- 17676
- 17677 mem_dp = &rmp->mp_seg[D]; /* pointer to data segment map */
- 17678 mem_sp = &rmp->mp_seg[S]; /* pointer to stack segment map */
- 17679 changed = 0; /* set when either segment changed */
- 17680
- 17681 if (mem_sp->mem_len == 0) return(OK); /* don't bother init */
- 17682
- 17683 /* See if stack size has gone negative (i.e., sp too close to 0xFFFF...) */
- 17684 base_of_stack = (long) mem_sp->mem_vir + (long) mem_sp->mem_len;
- 17685 sp_click = sp >> CLICK_SHIFT; /* click containing sp */
- 17686 if (sp_click >= base_of_stack) return(ENOMEM); /* sp too high */
- 17687
- 17688 /* Compute size of gap between stack and data segments. */
- 17689 delta = (long) mem_sp->mem_vir - (long) sp_click;
- 17690 lower = (delta > 0 ? sp_click : mem_sp->mem_vir);
- 17691
- 17692 /* Add a safety margin for future stack growth. Impossible to do right. */
- 17693 #define SAFETY_BYTES (384 * sizeof(char *))
- 17694 #define SAFETY_CLICKS ((SAFETY_BYTES + CLICK_SIZE - 1) / CLICK_SIZE)
- 17695 gap_base = mem_dp->mem_vir + data_clicks + SAFETY_CLICKS;
- 17696 if (lower < gap_base) return(ENOMEM); /* data and stack collided */
- 17697
- 17698 /* Update data length (but not data orgin) on behalf of brk() system call. */
- 17699 old_clicks = mem_dp->mem_len;
- 17700 if (data_clicks != mem_dp->mem_len) {
- 17701 mem_dp->mem_len = data_clicks;
- 17702 changed |= DATA_CHANGED;
- 17703 }
- 17704
- 17705 /* Update stack length and origin due to change in stack pointer. */
- 17706 if (delta > 0) {
- 17707 mem_sp->mem_vir -= delta;
- 17708 mem_sp->mem_phys -= delta;
- 17709 mem_sp->mem_len += delta;
- 17710 changed |= STACK_CHANGED;
- 17711 }
- 17712
- 17713 /* Do the new data and stack segment sizes fit in the address space? */
- 17714 ft = (rmp->mp_flags & SEPARATE);
- 17715 r = size_ok(ft, rmp->mp_seg[T].mem_len, rmp->mp_seg[D].mem_len,
- 17716 rmp->mp_seg[S].mem_len, rmp->mp_seg[D].mem_vir, rmp->mp_seg[S].mem_vir);
- 17717 if (r == OK) {
- 17718 if (changed) sys_newmap((int)(rmp - mproc), rmp->mp_seg);
- 17719 return(OK);
- 17720 }
- 17721
- 17722 /* New sizes don't fit or require too many page/segment registers. Restore.*/
- 17723 if (changed & DATA_CHANGED) mem_dp->mem_len = old_clicks;
- 17724 if (changed & STACK_CHANGED) {
- 17725 mem_sp->mem_vir += delta;
- 17726 mem_sp->mem_phys += delta;
- 17727 mem_sp->mem_len -= delta;
- 17728 }
- 17729 return(ENOMEM);
- 17730 }
-
-
- 17733 /*===========================================================================*
- 17734 * size_ok *
- 17735 *===========================================================================*/
- 17736 PUBLIC int size_ok(file_type, tc, dc, sc, dvir, s_vir)
- 17737 int file_type; /* SEPARATE or 0 */
- 17738 vir_clicks tc; /* text size in clicks */
- 17739 vir_clicks dc; /* data size in clicks */
- 17740 vir_clicks sc; /* stack size in clicks */
- 17741 vir_clicks dvir; /* virtual address for start of data seg */
- 17742 vir_clicks s_vir; /* virtual address for start of stack seg */
- 17743 {
- 17744 /* Check to see if the sizes are feasible and enough segmentation registers
- 17745 * exist. On a machine with eight 8K pages, text, data, stack sizes of
- 17746 * (32K, 16K, 16K) will fit, but (33K, 17K, 13K) will not, even though the
- 17747 * former is bigger (64K) than the latter (63K). Even on the 8088 this test
- 17748 * is needed, since the data and stack may not exceed 4096 clicks.
- 17749 */
- 17750
- 17751 #if (CHIP == INTEL && _WORD_SIZE == 2)
- 17752 int pt, pd, ps; /* segment sizes in pages */
- 17753
- 17754 pt = ( (tc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
- 17755 pd = ( (dc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
- 17756 ps = ( (sc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
- 17757
- 17758 if (file_type == SEPARATE) {
- 17759 if (pt > MAX_PAGES || pd + ps > MAX_PAGES) return(ENOMEM);
- 17760 } else {
- 17761 if (pt + pd + ps > MAX_PAGES) return(ENOMEM);
- 17762 }
- 17763 #endif
- 17764
- 17765 if (dvir + dc > s_vir) return(ENOMEM);
- 17766
- 17767 return(OK);
- 17768 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/mm/signal.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 17800 /* This file handles signals, which are asynchronous events and are generally
- 17801 * a messy and unpleasant business. Signals can be generated by the KILL
- 17802 * system call, or from the keyboard (SIGINT) or from the clock (SIGALRM).
- 17803 * In all cases control eventually passes to check_sig() to see which processes
- 17804 * can be signaled. The actual signaling is done by sig_proc().
- 17805 *
- 17806 * The entry points into this file are:
- 17807 * do_sigaction: perform the SIGACTION system call
- 17808 * do_sigpending: perform the SIGPENDING system call
- 17809 * do_sigprocmask: perform the SIGPROCMASK system call
- 17810 * do_sigreturn: perform the SIGRETURN system call
- 17811 * do_sigsuspend: perform the SIGSUSPEND system call
- 17812 * do_kill: perform the KILL system call
- 17813 * do_ksig: accept a signal originating in the kernel (e.g., SIGINT)
- 17814 * do_alarm: perform the ALARM system call by calling set_alarm()
- 17815 * set_alarm: tell the clock task to start or stop a timer
- 17816 * do_pause: perform the PAUSE system call
- 17817 * do_reboot: kill all processes, then reboot system
- 17818 * sig_proc: interrupt or terminate a signaled process
- 17819 * check_sig: check which processes to signal with sig_proc()
- 17820 */
- 17821
- 17822 #include "mm.h"
- 17823 #include <sys/stat.h>
- 17824 #include <minix/callnr.h>
- 17825 #include <minix/com.h>
- 17826 #include <signal.h>
- 17827 #include <sys/sigcontext.h>
- 17828 #include <string.h>
- 17829 #include "mproc.h"
- 17830 #include "param.h"
- 17831
- 17832 #define CORE_MODE 0777 /* mode to use on core image files */
- 17833 #define DUMPED 0200 /* bit set in status when core dumped */
- 17834 #define DUMP_SIZE ((INT_MAX / BLOCK_SIZE) * BLOCK_SIZE)
- 17835 /* buffer size for core dumps */
- 17836
- 17837 FORWARD _PROTOTYPE( void check_pending, (void) );
- 17838 FORWARD _PROTOTYPE( void dump_core, (struct mproc *rmp) );
- 17839 FORWARD _PROTOTYPE( void unpause, (int pro) );
- 17840
- 17841
- 17842 /*===========================================================================*
- 17843 * do_sigaction *
- 17844 *===========================================================================*/
- 17845 PUBLIC int do_sigaction()
- 17846 {
- 17847 int r;
- 17848 struct sigaction svec;
- 17849 struct sigaction *svp;
- 17850
- 17851 if (sig_nr == SIGKILL) return(OK);
- 17852 if (sig_nr < 1 || sig_nr > _NSIG) return (EINVAL);
- 17853 svp = &mp->mp_sigact[sig_nr];
- 17854 if ((struct sigaction *) sig_osa != (struct sigaction *) NULL) {
- 17855 r = sys_copy(MM_PROC_NR,D, (phys_bytes) svp,
- 17856 who, D, (phys_bytes) sig_osa, (phys_bytes) sizeof(svec));
- 17857 if (r != OK) return(r);
- 17858 }
- 17859
- 17860 if ((struct sigaction *) sig_nsa == (struct sigaction *) NULL) return(OK);
- 17861
- 17862 /* Read in the sigaction structure. */
- 17863 r = sys_copy(who, D, (phys_bytes) sig_nsa,
- 17864 MM_PROC_NR, D, (phys_bytes) &svec, (phys_bytes) sizeof(svec));
- 17865 if (r != OK) return(r);
- 17866
- 17867 if (svec.sa_handler == SIG_IGN) {
- 17868 sigaddset(&mp->mp_ignore, sig_nr);
- 17869 sigdelset(&mp->mp_sigpending, sig_nr);
- 17870 sigdelset(&mp->mp_catch, sig_nr);
- 17871 } else {
- 17872 sigdelset(&mp->mp_ignore, sig_nr);
- 17873 if (svec.sa_handler == SIG_DFL)
- 17874 sigdelset(&mp->mp_catch, sig_nr);
- 17875 else
- 17876 sigaddset(&mp->mp_catch, sig_nr);
- 17877 }
- 17878 mp->mp_sigact[sig_nr].sa_handler = svec.sa_handler;
- 17879 sigdelset(&svec.sa_mask, SIGKILL);
- 17880 mp->mp_sigact[sig_nr].sa_mask = svec.sa_mask;
- 17881 mp->mp_sigact[sig_nr].sa_flags = svec.sa_flags;
- 17882 mp->mp_sigreturn = (vir_bytes) sig_ret;
- 17883 return(OK);
- 17884 }
-
- 17886 /*===========================================================================*
- 17887 * do_sigpending *
- 17888 *===========================================================================*/
- 17889 PUBLIC int do_sigpending()
- 17890 {
- 17891 ret_mask = (long) mp->mp_sigpending;
- 17892 return OK;
- 17893 }
-
- 17895 /*===========================================================================*
- 17896 * do_sigprocmask *
- 17897 *===========================================================================*/
- 17898 PUBLIC int do_sigprocmask()
- 17899 {
- 17900 /* Note that the library interface passes the actual mask in sigmask_set,
- 17901 * not a pointer to the mask, in order to save a sys_copy. Similarly,
- 17902 * the old mask is placed in the return message which the library
- 17903 * interface copies (if requested) to the user specified address.
- 17904 *
- 17905 * The library interface must set SIG_INQUIRE if the 'act' argument
- 17906 * is NULL.
- 17907 */
- 17908
- 17909 int i;
- 17910
- 17911 ret_mask = (long) mp->mp_sigmask;
- 17912
- 17913 switch (sig_how) {
- 17914 case SIG_BLOCK:
- 17915 sigdelset((sigset_t *)&sig_set, SIGKILL);
- 17916 for (i = 1; i < _NSIG; i++) {
- 17917 if (sigismember((sigset_t *)&sig_set, i))
- 17918 sigaddset(&mp->mp_sigmask, i);
- 17919 }
- 17920 break;
- 17921
- 17922 case SIG_UNBLOCK:
- 17923 for (i = 1; i < _NSIG; i++) {
- 17924 if (sigismember((sigset_t *)&sig_set, i))
- 17925 sigdelset(&mp->mp_sigmask, i);
- 17926 }
- 17927 check_pending();
- 17928 break;
- 17929
- 17930 case SIG_SETMASK:
- 17931 sigdelset((sigset_t *)&sig_set, SIGKILL);
- 17932 mp->mp_sigmask = (sigset_t)sig_set;
- 17933 check_pending();
- 17934 break;
- 17935
- 17936 case SIG_INQUIRE:
- 17937 break;
- 17938
- 17939 default:
- 17940 return(EINVAL);
- 17941 break;
- 17942 }
- 17943 return OK;
- 17944 }
-
- 17946 /*===========================================================================*
- 17947 * do_sigsuspend *
- 17948 *===========================================================================*/
- 17949 PUBLIC int do_sigsuspend()
- 17950 {
- 17951 mp->mp_sigmask2 = mp->mp_sigmask; /* save the old mask */
- 17952 mp->mp_sigmask = (sigset_t) sig_set;
- 17953 sigdelset(&mp->mp_sigmask, SIGKILL);
- 17954 mp->mp_flags |= SIGSUSPENDED;
- 17955 dont_reply = TRUE;
- 17956 check_pending();
- 17957 return OK;
- 17958 }
-
-
- 17961 /*===========================================================================*
- 17962 * do_sigreturn *
- 17963 *===========================================================================*/
- 17964 PUBLIC int do_sigreturn()
- 17965 {
- 17966 /* A user signal handler is done. Restore context and check for
- 17967 * pending unblocked signals.
- 17968 */
- 17969
- 17970 int r;
- 17971
- 17972 mp->mp_sigmask = (sigset_t) sig_set;
- 17973 sigdelset(&mp->mp_sigmask, SIGKILL);
- 17974
- 17975 r = sys_sigreturn(who, (vir_bytes)sig_context, sig_flags);
- 17976 check_pending();
- 17977 return(r);
- 17978 }
-
- 17980 /*===========================================================================*
- 17981 * do_kill *
- 17982 *===========================================================================*/
- 17983 PUBLIC int do_kill()
- 17984 {
- 17985 /* Perform the kill(pid, signo) system call. */
- 17986
- 17987 return check_sig(pid, sig_nr);
- 17988 }
-
-
- 17991 /*===========================================================================*
- 17992 * do_ksig *
- 17993 *===========================================================================*/
- 17994 PUBLIC int do_ksig()
- 17995 {
- 17996 /* Certain signals, such as segmentation violations and DEL, originate in the
- 17997 * kernel. When the kernel detects such signals, it sets bits in a bit map.
- 17998 * As soon as MM is awaiting new work, the kernel sends MM a message containing
- 17999 * the process slot and bit map. That message comes here. The File System
- 18000 * also uses this mechanism to signal writing on broken pipes (SIGPIPE).
- 18001 */
- 18002
- 18003 register struct mproc *rmp;
- 18004 int i, proc_nr;
- 18005 pid_t proc_id, id;
- 18006 sigset_t sig_map;
- 18007
- 18008 /* Only kernel may make this call. */
- 18009 if (who != HARDWARE) return(EPERM);
- 18010 dont_reply = TRUE; /* don't reply to the kernel */
- 18011 proc_nr = mm_in.SIG_PROC;
- 18012 rmp = &mproc[proc_nr];
- 18013 if ( (rmp->mp_flags & IN_USE) == 0 || (rmp->mp_flags & HANGING) ) return(OK);
- 18014 proc_id = rmp->mp_pid;
- 18015 sig_map = (sigset_t) mm_in.SIG_MAP;
- 18016 mp = &mproc[0]; /* pretend kernel signals are from MM */
- 18017 mp->mp_procgrp = rmp->mp_procgrp; /* get process group right */
- 18018
- 18019 /* Check each bit in turn to see if a signal is to be sent. Unlike
- 18020 * kill(), the kernel may collect several unrelated signals for a
- 18021 * process and pass them to MM in one blow. Thus loop on the bit
- 18022 * map. For SIGINT and SIGQUIT, use proc_id 0 to indicate a broadcast
- 18023 * to the recipient's process group. For SIGKILL, use proc_id -1 to
- 18024 * indicate a systemwide broadcast.
- 18025 */
- 18026 for (i = 1; i <= _NSIG; i++) {
- 18027 if (!sigismember(&sig_map, i)) continue;
- 18028 switch (i) {
- 18029 case SIGINT:
- 18030 case SIGQUIT:
- 18031 id = 0; break; /* broadcast to process group */
- 18032 case SIGKILL:
- 18033 id = -1; break; /* broadcast to all except INIT */
- 18034 case SIGALRM:
- 18035 /* Disregard SIGALRM when the target process has not
- 18036 * requested an alarm. This only applies for a KERNEL
- 18037 * generated signal.
- 18038 */
- 18039 if ((rmp->mp_flags & ALARM_ON) == 0) continue;
- 18040 rmp->mp_flags &= ~ALARM_ON;
- 18041 /* fall through */
- 18042 default:
- 18043 id = proc_id;
- 18044 break;
- 18045 }
- 18046 check_sig(id, i);
- 18047 sys_endsig(proc_nr); /* tell kernel it's done */
- 18048 }
- 18049 return(OK);
- 18050 }
-
-
- 18053 /*===========================================================================*
- 18054 * do_alarm *
- 18055 *===========================================================================*/
- 18056 PUBLIC int do_alarm()
- 18057 {
- 18058 /* Perform the alarm(seconds) system call. */
- 18059
- 18060 return(set_alarm(who, seconds));
- 18061 }
-
-
- 18064 /*===========================================================================*
- 18065 * set_alarm *
- 18066 *===========================================================================*/
- 18067 PUBLIC int set_alarm(proc_nr, sec)
- 18068 int proc_nr; /* process that wants the alarm */
- 18069 int sec; /* how many seconds delay before the signal */
- 18070 {
- 18071 /* This routine is used by do_alarm() to set the alarm timer. It is also used
- 18072 * to turn the timer off when a process exits with the timer still on.
- 18073 */
- 18074
- 18075 message m_sig;
- 18076 int remaining;
- 18077
- 18078 if (sec != 0)
- 18079 mproc[proc_nr].mp_flags |= ALARM_ON;
- 18080 else
- 18081 mproc[proc_nr].mp_flags &= ~ALARM_ON;
- 18082
- 18083 /* Tell the clock task to provide a signal message when the time comes.
- 18084 *
- 18085 * Large delays cause a lot of problems. First, the alarm system call
- 18086 * takes an unsigned seconds count and the library has cast it to an int.
- 18087 * That probably works, but on return the library will convert "negative"
- 18088 * unsigneds to errors. Presumably no one checks for these errors, so
- 18089 * force this call through. Second, If unsigned and long have the same
- 18090 * size, converting from seconds to ticks can easily overflow. Finally,
- 18091 * the kernel has similar overflow bugs adding ticks.
- 18092 *
- 18093 * Fixing this requires a lot of ugly casts to fit the wrong interface
- 18094 * types and to avoid overflow traps. DELTA_TICKS has the right type
- 18095 * (clock_t) although it is declared as long. How can variables like
- 18096 * this be declared properly without combinatorial explosion of message
- 18097 * types?
- 18098 */
- 18099 m_sig.m_type = SET_ALARM;
- 18100 m_sig.CLOCK_PROC_NR = proc_nr;
- 18101 m_sig.DELTA_TICKS = (clock_t) (HZ * (unsigned long) (unsigned) sec);
- 18102 if ( (unsigned long) m_sig.DELTA_TICKS / HZ != (unsigned) sec)
- 18103 m_sig.DELTA_TICKS = LONG_MAX; /* eternity (really CLOCK_T_MAX) */
- 18104 if (sendrec(CLOCK, &m_sig) != OK) panic("alarm er", NO_NUM);
- 18105 remaining = (int) m_sig.SECONDS_LEFT;
- 18106 if (remaining != m_sig.SECONDS_LEFT || remaining < 0)
- 18107 remaining = INT_MAX; /* true value is not representable */
- 18108 return(remaining);
- 18109 }
-
-
- 18112 /*===========================================================================*
- 18113 * do_pause *
- 18114 *===========================================================================*/
- 18115 PUBLIC int do_pause()
- 18116 {
- 18117 /* Perform the pause() system call. */
- 18118
- 18119 mp->mp_flags |= PAUSED;
- 18120 dont_reply = TRUE;
- 18121 return(OK);
- 18122 }
-
-
- 18125 /*=====================================================================*
- 18126 * do_reboot *
- 18127 *=====================================================================*/
- 18128 PUBLIC int do_reboot()
- 18129 {
- 18130 register struct mproc *rmp = mp;
- 18131 char monitor_code[64];
- 18132
- 18133 if (rmp->mp_effuid != SUPER_USER) return EPERM;
- 18134
- 18135 switch (reboot_flag) {
- 18136 case RBT_HALT:
- 18137 case RBT_REBOOT:
- 18138 case RBT_PANIC:
- 18139 case RBT_RESET:
- 18140 break;
- 18141 case RBT_MONITOR:
- 18142 if (reboot_size > sizeof(monitor_code)) return EINVAL;
- 18143 memset(monitor_code, 0, sizeof(monitor_code));
- 18144 if (sys_copy(who, D, (phys_bytes) reboot_code,
- 18145 MM_PROC_NR, D, (phys_bytes) monitor_code,
- 18146 (phys_bytes) reboot_size) != OK) return EFAULT;
- 18147 if (monitor_code[sizeof(monitor_code)-1] != 0) return EINVAL;
- 18148 break;
- 18149 default:
- 18150 return EINVAL;
- 18151 }
- 18152
- 18153 /* Kill all processes except init. */
- 18154 check_sig(-1, SIGKILL);
- 18155
- 18156 tell_fs(EXIT, INIT_PROC_NR, 0, 0); /* cleanup init */
- 18157
- 18158 tell_fs(SYNC,0,0,0);
- 18159
- 18160 sys_abort(reboot_flag, monitor_code);
- 18161 /* NOTREACHED */
- 18162 }
-
-
- 18165 /*===========================================================================*
- 18166 * sig_proc *
- 18167 *===========================================================================*/
- 18168 PUBLIC void sig_proc(rmp, signo)
- 18169 register struct mproc *rmp; /* pointer to the process to be signaled */
- 18170 int signo; /* signal to send to process (1 to _NSIG) */
- 18171 {
- 18172 /* Send a signal to a process. Check to see if the signal is to be caught,
- 18173 * ignored, or blocked. If the signal is to be caught, coordinate with
- 18174 * KERNEL to push a sigcontext structure and a sigframe structure onto
- 18175 * the catcher's stack. Also, KERNEL will reset the program counter and
- 18176 * stack pointer, so that when the process next runs, it will be executing
- 18177 * the signal handler. When the signal handler returns, sigreturn(2)
- 18178 * will be called. Then KERNEL will restore the signal context from the
- 18179 * sigcontext structure.
- 18180 *
- 18181 * If there is insufficient stack space, kill the process.
- 18182 */
- 18183
- 18184 vir_bytes new_sp;
- 18185 int slot;
- 18186 int sigflags;
- 18187 struct sigmsg sm;
- 18188
- 18189 slot = (int) (rmp - mproc);
- 18190 if (!(rmp->mp_flags & IN_USE)) {
- 18191 printf("MM: signal %d sent to dead process %dn", signo, slot);
- 18192 panic("", NO_NUM);
- 18193 }
- 18194 if (rmp->mp_flags & HANGING) {
- 18195 printf("MM: signal %d sent to HANGING process %dn", signo, slot);
- 18196 panic("", NO_NUM);
- 18197 }
- 18198 if (rmp->mp_flags & TRACED && signo != SIGKILL) {
- 18199 /* A traced process has special handling. */
- 18200 unpause(slot);
- 18201 stop_proc(rmp, signo); /* a signal causes it to stop */
- 18202 return;
- 18203 }
- 18204 /* Some signals are ignored by default. */
- 18205 if (sigismember(&rmp->mp_ignore, signo)) return;
- 18206
- 18207 if (sigismember(&rmp->mp_sigmask, signo)) {
- 18208 /* Signal should be blocked. */
- 18209 sigaddset(&rmp->mp_sigpending, signo);
- 18210 return;
- 18211 }
- 18212 sigflags = rmp->mp_sigact[signo].sa_flags;
- 18213 if (sigismember(&rmp->mp_catch, signo)) {
- 18214 if (rmp->mp_flags & SIGSUSPENDED)
- 18215 sm.sm_mask = rmp->mp_sigmask2;
- 18216 else
- 18217 sm.sm_mask = rmp->mp_sigmask;
- 18218 sm.sm_signo = signo;
- 18219 sm.sm_sighandler = (vir_bytes) rmp->mp_sigact[signo].sa_handler;
- 18220 sm.sm_sigreturn = rmp->mp_sigreturn;
- 18221 sys_getsp(slot, &new_sp);
- 18222 sm.sm_stkptr = new_sp;
- 18223
- 18224 /* Make room for the sigcontext and sigframe struct. */
- 18225 new_sp -= sizeof(struct sigcontext)
- 18226 + 3 * sizeof(char *) + 2 * sizeof(int);
- 18227
- 18228 if (adjust(rmp, rmp->mp_seg[D].mem_len, new_sp) != OK)
- 18229 goto doterminate;
- 18230
- 18231 rmp->mp_sigmask |= rmp->mp_sigact[signo].sa_mask;
- 18232 if (sigflags & SA_NODEFER)
- 18233 sigdelset(&rmp->mp_sigmask, signo);
- 18234 else
- 18235 sigaddset(&rmp->mp_sigmask, signo);
- 18236
- 18237 if (sigflags & SA_RESETHAND) {
- 18238 sigdelset(&rmp->mp_catch, signo);
- 18239 rmp->mp_sigact[signo].sa_handler = SIG_DFL;
- 18240 }
- 18241
- 18242 sys_sendsig(slot, &sm);
- 18243 sigdelset(&rmp->mp_sigpending, signo);
- 18244 /* If process is hanging on PAUSE, WAIT, SIGSUSPEND, tty, pipe, etc.,
- 18245 * release it.
- 18246 */
- 18247 unpause(slot);
- 18248 return;
- 18249 }
- 18250 doterminate:
- 18251 /* Signal should not or cannot be caught. Terminate the process. */
- 18252 rmp->mp_sigstatus = (char) signo;
- 18253 if (sigismember(&core_sset, signo)) {
- 18254 /* Switch to the user's FS environment and dump core. */
- 18255 tell_fs(CHDIR, slot, FALSE, 0);
- 18256 dump_core(rmp);
- 18257 }
- 18258 mm_exit(rmp, 0); /* terminate process */
- 18259 }
-
-
- 18262 /*===========================================================================*
- 18263 * check_sig *
- 18264 *===========================================================================*/
- 18265 PUBLIC int check_sig(proc_id, signo)
- 18266 pid_t proc_id; /* pid of proc to sig, or 0 or -1, or -pgrp */
- 18267 int signo; /* signal to send to process (0 to _NSIG) */
- 18268 {
- 18269 /* Check to see if it is possible to send a signal. The signal may have to be
- 18270 * sent to a group of processes. This routine is invoked by the KILL system
- 18271 * call, and also when the kernel catches a DEL or other signal.
- 18272 */
- 18273
- 18274 register struct mproc *rmp;
- 18275 int count; /* count # of signals sent */
- 18276 int error_code;
- 18277
- 18278 if (signo < 0 || signo > _NSIG) return(EINVAL);
- 18279
- 18280 /* Return EINVAL for attempts to send SIGKILL to INIT alone. */
- 18281 if (proc_id == INIT_PID && signo == SIGKILL) return(EINVAL);
- 18282
- 18283 /* Search the proc table for processes to signal. (See forkexit.c about
- 18284 * pid magic.)
- 18285 */
- 18286 count = 0;
- 18287 error_code = ESRCH;
- 18288 for (rmp = &mproc[INIT_PROC_NR]; rmp < &mproc[NR_PROCS]; rmp++) {
- 18289 if ( (rmp->mp_flags & IN_USE) == 0) continue;
- 18290 if (rmp->mp_flags & HANGING && signo != 0) continue;
- 18291
- 18292 /* Check for selection. */
- 18293 if (proc_id > 0 && proc_id != rmp->mp_pid) continue;
- 18294 if (proc_id == 0 && mp->mp_procgrp != rmp->mp_procgrp) continue;
- 18295 if (proc_id == -1 && rmp->mp_pid == INIT_PID) continue;
- 18296 if (proc_id < -1 && rmp->mp_procgrp != -proc_id) continue;
- 18297
- 18298 /* Check for permission. */
- 18299 if (mp->mp_effuid != SUPER_USER
- 18300 && mp->mp_realuid != rmp->mp_realuid
- 18301 && mp->mp_effuid != rmp->mp_realuid
- 18302 && mp->mp_realuid != rmp->mp_effuid
- 18303 && mp->mp_effuid != rmp->mp_effuid) {
- 18304 error_code = EPERM;
- 18305 continue;
- 18306 }
- 18307
- 18308 count++;
- 18309 if (signo == 0) continue;
- 18310
- 18311 /* 'sig_proc' will handle the disposition of the signal. The
- 18312 * signal may be caught, blocked, ignored, or cause process
- 18313 * termination, possibly with core dump.
- 18314 */
- 18315 sig_proc(rmp, signo);
- 18316
- 18317 if (proc_id > 0) break; /* only one process being signaled */
- 18318 }
- 18319
- 18320 /* If the calling process has killed itself, don't reply. */
- 18321 if ((mp->mp_flags & IN_USE) == 0 || (mp->mp_flags & HANGING))
- 18322 dont_reply = TRUE;
- 18323 return(count > 0 ? OK : error_code);
- 18324 }
-
-
- 18327 /*===========================================================================*
- 18328 * check_pending *
- 18329 *===========================================================================*/
- 18330 PRIVATE void check_pending()
- 18331 {
- 18332 /* Check to see if any pending signals have been unblocked. The
- 18333 * first such signal found is delivered.
- 18334 *
- 18335 * If multiple pending unmasked signals are found, they will be
- 18336 * delivered sequentially.
- 18337 *
- 18338 * There are several places in this file where the signal mask is
- 18339 * changed. At each such place, check_pending() should be called to
- 18340 * check for newly unblocked signals.
- 18341 */
- 18342
- 18343 int i;
- 18344
- 18345 for (i = 1; i < _NSIG; i++) {
- 18346 if (sigismember(&mp->mp_sigpending, i) &&
- 18347 !sigismember(&mp->mp_sigmask, i)) {
- 18348 sigdelset(&mp->mp_sigpending, i);
- 18349 sig_proc(mp, i);
- 18350 break;
- 18351 }
- 18352 }
- 18353 }
-
-
- 18356 /*===========================================================================*
- 18357 * unpause *
- 18358 *===========================================================================*/
- 18359 PRIVATE void unpause(pro)
- 18360 int pro; /* which process number */
- 18361 {
- 18362 /* A signal is to be sent to a process. If that process is hanging on a
- 18363 * system call, the system call must be terminated with EINTR. Possible
- 18364 * calls are PAUSE, WAIT, READ and WRITE, the latter two for pipes and ttys.
- 18365 * First check if the process is hanging on an MM call. If not, tell FS,
- 18366 * so it can check for READs and WRITEs from pipes, ttys and the like.
- 18367 */
- 18368
- 18369 register struct mproc *rmp;
- 18370
- 18371 rmp = &mproc[pro];
- 18372
- 18373 /* Check to see if process is hanging on a PAUSE call. */
- 18374 if ( (rmp->mp_flags & PAUSED) && (rmp->mp_flags & HANGING) == 0) {
- 18375 rmp->mp_flags &= ~PAUSED;
- 18376 reply(pro, EINTR, 0, NIL_PTR);
- 18377 return;
- 18378 }
- 18379
- 18380 /* Check to see if process is hanging on a WAIT call. */
- 18381 if ( (rmp->mp_flags & WAITING) && (rmp->mp_flags & HANGING) == 0) {
- 18382 rmp->mp_flags &= ~WAITING;
- 18383 reply(pro, EINTR, 0, NIL_PTR);
- 18384 return;
- 18385 }
- 18386
- 18387 /* Check to see if process is hanging on a SIGSUSPEND call. */
- 18388 if ((rmp->mp_flags & SIGSUSPENDED) && (rmp->mp_flags & HANGING) == 0) {
- 18389 rmp->mp_flags &= ~SIGSUSPENDED;
- 18390 reply(pro, EINTR, 0, NIL_PTR);
- 18391 return;
- 18392 }
- 18393
- 18394 /* Process is not hanging on an MM call. Ask FS to take a look. */
- 18395 tell_fs(UNPAUSE, pro, 0, 0);
- 18396 }
-
-
- 18399 /*===========================================================================*
- 18400 * dump_core *
- 18401 *===========================================================================*/
- 18402 PRIVATE void dump_core(rmp)
- 18403 register struct mproc *rmp; /* whose core is to be dumped */
- 18404 {
- 18405 /* Make a core dump on the file "core", if possible. */
- 18406
- 18407 int fd, fake_fd, nr_written, seg, slot;
- 18408 char *buf;
- 18409 vir_bytes current_sp;
- 18410 phys_bytes left; /* careful; 64K might overflow vir_bytes */
- 18411 unsigned nr_to_write; /* unsigned for arg to write() but < INT_MAX */
- 18412 long trace_data, trace_off;
- 18413
- 18414 slot = (int) (rmp - mproc);
- 18415
- 18416 /* Can core file be written? We are operating in the user's FS environment,
- 18417 * so no special permission checks are needed.
- 18418 */
- 18419 if (rmp->mp_realuid != rmp->mp_effuid) return;
- 18420 if ( (fd = creat(core_name, CORE_MODE)) < 0) return;
- 18421 rmp->mp_sigstatus |= DUMPED;
- 18422
- 18423 /* Make sure the stack segment is up to date.
- 18424 * We don't want adjust() to fail unless current_sp is preposterous,
- 18425 * but it might fail due to safety checking. Also, we don't really want
- 18426 * the adjust() for sending a signal to fail due to safety checking.
- 18427 * Maybe make SAFETY_BYTES a parameter.
- 18428 */
- 18429 sys_getsp(slot, ¤t_sp);
- 18430 adjust(rmp, rmp->mp_seg[D].mem_len, current_sp);
- 18431
- 18432 /* Write the memory map of all segments to begin the core file. */
- 18433 if (write(fd, (char *) rmp->mp_seg, (unsigned) sizeof rmp->mp_seg)
- 18434 != (unsigned) sizeof rmp->mp_seg) {
- 18435 close(fd);
- 18436 return;
- 18437 }
- 18438
- 18439 /* Write out the whole kernel process table entry to get the regs. */
- 18440 trace_off = 0;
- 18441 while (sys_trace(3, slot, trace_off, &trace_data) == OK) {
- 18442 if (write(fd, (char *) &trace_data, (unsigned) sizeof (long))
- 18443 != (unsigned) sizeof (long)) {
- 18444 close(fd);
- 18445 return;
- 18446 }
- 18447 trace_off += sizeof (long);
- 18448 }
- 18449
- 18450 /* Loop through segments and write the segments themselves out. */
- 18451 for (seg = 0; seg < NR_SEGS; seg++) {
- 18452 buf = (char *) ((vir_bytes) rmp->mp_seg[seg].mem_vir << CLICK_SHIFT);
- 18453 left = (phys_bytes) rmp->mp_seg[seg].mem_len << CLICK_SHIFT;
- 18454 fake_fd = (slot << 8) | (seg << 6) | fd;
- 18455
- 18456 /* Loop through a segment, dumping it. */
- 18457 while (left != 0) {
- 18458 nr_to_write = (unsigned) MIN(left, DUMP_SIZE);
- 18459 if ( (nr_written = write(fake_fd, buf, nr_to_write)) < 0) {
- 18460 close(fd);
- 18461 return;
- 18462 }
- 18463 buf += nr_written;
- 18464 left -= nr_written;
- 18465 }
- 18466 }
- 18467 close(fd);
- 18468 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/mm/getset.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 18500 /* This file handles the 4 system calls that get and set uids and gids.
- 18501 * It also handles getpid(), setsid(), and getpgrp(). The code for each
- 18502 * one is so tiny that it hardly seemed worthwhile to make each a separate
- 18503 * function.
- 18504 */
- 18505
- 18506 #include "mm.h"
- 18507 #include <minix/callnr.h>
- 18508 #include <signal.h>
- 18509 #include "mproc.h"
- 18510 #include "param.h"
- 18511
- 18512 /*===========================================================================*
- 18513 * do_getset *
- 18514 *===========================================================================*/
- 18515 PUBLIC int do_getset()
- 18516 {
- 18517 /* Handle GETUID, GETGID, GETPID, GETPGRP, SETUID, SETGID, SETSID. The four
- 18518 * GETs and SETSID return their primary results in 'r'. GETUID, GETGID, and
- 18519 * GETPID also return secondary results (the effective IDs, or the parent
- 18520 * process ID) in 'result2', which is returned to the user.
- 18521 */
- 18522
- 18523 register struct mproc *rmp = mp;
- 18524 register int r;
- 18525
- 18526 switch(mm_call) {
- 18527 case GETUID:
- 18528 r = rmp->mp_realuid;
- 18529 result2 = rmp->mp_effuid;
- 18530 break;
- 18531
- 18532 case GETGID:
- 18533 r = rmp->mp_realgid;
- 18534 result2 = rmp->mp_effgid;
- 18535 break;
- 18536
- 18537 case GETPID:
- 18538 r = mproc[who].mp_pid;
- 18539 result2 = mproc[rmp->mp_parent].mp_pid;
- 18540 break;
- 18541
- 18542 case SETUID:
- 18543 if (rmp->mp_realuid != usr_id && rmp->mp_effuid != SUPER_USER)
- 18544 return(EPERM);
- 18545 rmp->mp_realuid = usr_id;
- 18546 rmp->mp_effuid = usr_id;
- 18547 tell_fs(SETUID, who, usr_id, usr_id);
- 18548 r = OK;
- 18549 break;
- 18550
- 18551 case SETGID:
- 18552 if (rmp->mp_realgid != grpid && rmp->mp_effuid != SUPER_USER)
- 18553 return(EPERM);
- 18554 rmp->mp_realgid = grpid;
- 18555 rmp->mp_effgid = grpid;
- 18556 tell_fs(SETGID, who, grpid, grpid);
- 18557 r = OK;
- 18558 break;
- 18559
- 18560 case SETSID:
- 18561 if (rmp->mp_procgrp == rmp->mp_pid) return(EPERM);
- 18562 rmp->mp_procgrp = rmp->mp_pid;
- 18563 tell_fs(SETSID, who, 0, 0);
- 18564 /*FALL THROUGH*/
- 18565
- 18566 case GETPGRP:
- 18567 r = rmp->mp_procgrp;
- 18568 break;
- 18569
- 18570 default:
- 18571 r = EINVAL;
- 18572 break;
- 18573 }
- 18574 return(r);
- 18575 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/mm/trace.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 18600 /* This file handles the memory manager's part of debugging, using the
- 18601 * ptrace system call. Most of the commands are passed on to the system
- 18602 * task for completion.
- 18603 *
- 18604 * The debugging commands available are:
- 18605 * T_STOP stop the process
- 18606 * T_OK enable tracing by parent for this process
- 18607 * T_GETINS return value from instruction space
- 18608 * T_GETDATA return value from data space
- 18609 * T_GETUSER return value from user process table
- 18610 * T_SETINS set value in instruction space
- 18611 * T_SETDATA set value in data space
- 18612 * T_SETUSER set value in user process table
- 18613 * T_RESUME resume execution
- 18614 * T_EXIT exit
- 18615 * T_STEP set trace bit
- 18616 *
- 18617 * The T_OK and T_EXIT commands are handled here, and the T_RESUME and
- 18618 * T_STEP commands are partially handled here and completed by the system
- 18619 * task. The rest are handled entirely by the system task.
- 18620 */
- 18621
- 18622 #include "mm.h"
- 18623 #include <sys/ptrace.h>
- 18624 #include <signal.h>
- 18625 #include "mproc.h"
- 18626 #include "param.h"
- 18627
- 18628 #define NIL_MPROC ((struct mproc *) 0)
- 18629
- 18630 FORWARD _PROTOTYPE( struct mproc *findproc, (pid_t lpid) );
- 18631
- 18632 /*===========================================================================*
- 18633 * do_trace *
- 18634 *===========================================================================*/
- 18635 PUBLIC int do_trace()
- 18636 {
- 18637 register struct mproc *child;
- 18638
- 18639 /* the T_OK call is made by the child fork of the debugger before it execs
- 18640 * the process to be traced
- 18641 */
- 18642 if (request == T_OK) {/* enable tracing by parent for this process */
- 18643 mp->mp_flags |= TRACED;
- 18644 mm_out.m2_l2 = 0;
- 18645 return(OK);
- 18646 }
- 18647 if ((child = findproc(pid)) == NIL_MPROC || !(child->mp_flags & STOPPED)) {
- 18648 return(ESRCH);
- 18649 }
- 18650 /* all the other calls are made by the parent fork of the debugger to
- 18651 * control execution of the child
- 18652 */
- 18653 switch (request) {
- 18654 case T_EXIT: /* exit */
- 18655 mm_exit(child, (int)data);
- 18656 mm_out.m2_l2 = 0;
- 18657 return(OK);
- 18658 case T_RESUME:
- 18659 case T_STEP: /* resume execution */
- 18660 if (data < 0 || data > _NSIG) return(EIO);
- 18661 if (data > 0) { /* issue signal */
- 18662 child->mp_flags &= ~TRACED; /* so signal is not diverted */
- 18663 sig_proc(child, (int) data);
- 18664 child->mp_flags |= TRACED;
- 18665 }
- 18666 child->mp_flags &= ~STOPPED;
- 18667 break;
- 18668 }
- 18669 if (sys_trace(request, (int) (child - mproc), taddr, &data) != OK)
- 18670 return(-errno);
- 18671 mm_out.m2_l2 = data;
- 18672 return(OK);
- 18673 }
-
- 18675 /*===========================================================================*
- 18676 * findproc *
- 18677 *===========================================================================*/
- 18678 PRIVATE struct mproc *findproc(lpid)
- 18679 pid_t lpid;
- 18680 {
- 18681 register struct mproc *rmp;
- 18682
- 18683 for (rmp = &mproc[INIT_PROC_NR + 1]; rmp < &mproc[NR_PROCS]; rmp++)
- 18684 if (rmp->mp_flags & IN_USE && rmp->mp_pid == lpid) return(rmp);
- 18685 return(NIL_MPROC);
- 18686 }
-
- 18688 /*===========================================================================*
- 18689 * stop_proc *
- 18690 *===========================================================================*/
- 18691 PUBLIC void stop_proc(rmp, signo)
- 18692 register struct mproc *rmp;
- 18693 int signo;
- 18694 {
- 18695 /* A traced process got a signal so stop it. */
- 18696
- 18697 register struct mproc *rpmp = mproc + rmp->mp_parent;
- 18698
- 18699 if (sys_trace(-1, (int) (rmp - mproc), 0L, (long *) 0) != OK) return;
- 18700 rmp->mp_flags |= STOPPED;
- 18701 if (rpmp->mp_flags & WAITING) {
- 18702 rpmp->mp_flags &= ~WAITING; /* parent is no longer waiting */
- 18703 reply(rmp->mp_parent, rmp->mp_pid, 0177 | (signo << 8), NIL_PTR);
- 18704 } else {
- 18705 rmp->mp_sigstatus = signo;
- 18706 }
- 18707 return;
- 18708 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/mm/alloc.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 18800 /* This file is concerned with allocating and freeing arbitrary-size blocks of
- 18801 * physical memory on behalf of the FORK and EXEC system calls. The key data
- 18802 * structure used is the hole table, which maintains a list of holes in memory.
- 18803 * It is kept sorted in order of increasing memory address. The addresses
- 18804 * it contains refer to physical memory, starting at absolute address 0
- 18805 * (i.e., they are not relative to the start of MM). During system
- 18806 * initialization, that part of memory containing the interrupt vectors,
- 18807 * kernel, and MM are "allocated" to mark them as not available and to
- 18808 * remove them from the hole list.
- 18809 *
- 18810 * The entry points into this file are:
- 18811 * alloc_mem: allocate a given sized chunk of memory
- 18812 * free_mem: release a previously allocated chunk of memory
- 18813 * mem_init: initialize the tables when MM start up
- 18814 * max_hole: returns the largest hole currently available
- 18815 */
- 18816
- 18817 #include "mm.h"
- 18818 #include <minix/com.h>
- 18819
- 18820 #define NR_HOLES 128 /* max # entries in hole table */
- 18821 #define NIL_HOLE (struct hole *) 0
- 18822
- 18823 PRIVATE struct hole {
- 18824 phys_clicks h_base; /* where does the hole begin? */
- 18825 phys_clicks h_len; /* how big is the hole? */
- 18826 struct hole *h_next; /* pointer to next entry on the list */
- 18827 } hole[NR_HOLES];
- 18828
- 18829
- 18830 PRIVATE struct hole *hole_head; /* pointer to first hole */
- 18831 PRIVATE struct hole *free_slots; /* ptr to list of unused table slots */
- 18832
- 18833 FORWARD _PROTOTYPE( void del_slot, (struct hole *prev_ptr, struct hole *hp) );
- 18834 FORWARD _PROTOTYPE( void merge, (struct hole *hp) );
- 18835
- 18836
- 18837 /*===========================================================================*
- 18838 * alloc_mem *
- 18839 *===========================================================================*/
- 18840 PUBLIC phys_clicks alloc_mem(clicks)
- 18841 phys_clicks clicks; /* amount of memory requested */
- 18842 {
- 18843 /* Allocate a block of memory from the free list using first fit. The block
- 18844 * consists of a sequence of contiguous bytes, whose length in clicks is
- 18845 * given by 'clicks'. A pointer to the block is returned. The block is
- 18846 * always on a click boundary. This procedure is called when memory is
- 18847 * needed for FORK or EXEC.
- 18848 */
- 18849
- 18850 register struct hole *hp, *prev_ptr;
- 18851 phys_clicks old_base;
- 18852
- 18853 hp = hole_head;
- 18854 while (hp != NIL_HOLE) {
- 18855 if (hp->h_len >= clicks) {
- 18856 /* We found a hole that is big enough. Use it. */
- 18857 old_base = hp->h_base; /* remember where it started */
- 18858 hp->h_base += clicks; /* bite a piece off */
- 18859 hp->h_len -= clicks; /* ditto */
- 18860
- 18861 /* If hole is only partly used, reduce size and return. */
- 18862 if (hp->h_len != 0) return(old_base);
- 18863
- 18864 /* The entire hole has been used up. Manipulate free list. */
- 18865 del_slot(prev_ptr, hp);
- 18866 return(old_base);
- 18867 }
- 18868
- 18869 prev_ptr = hp;
- 18870 hp = hp->h_next;
- 18871 }
- 18872 return(NO_MEM);
- 18873 }
-
-
- 18876 /*===========================================================================*
- 18877 * free_mem *
- 18878 *===========================================================================*/
- 18879 PUBLIC void free_mem(base, clicks)
- 18880 phys_clicks base; /* base address of block to free */
- 18881 phys_clicks clicks; /* number of clicks to free */
- 18882 {
- 18883 /* Return a block of free memory to the hole list. The parameters tell where
- 18884 * the block starts in physical memory and how big it is. The block is added
- 18885 * to the hole list. If it is contiguous with an existing hole on either end,
- 18886 * it is merged with the hole or holes.
- 18887 */
- 18888
- 18889 register struct hole *hp, *new_ptr, *prev_ptr;
- 18890
- 18891 if (clicks == 0) return;
- 18892 if ( (new_ptr = free_slots) == NIL_HOLE) panic("Hole table full", NO_NUM);
- 18893 new_ptr->h_base = base;
- 18894 new_ptr->h_len = clicks;
- 18895 free_slots = new_ptr->h_next;
- 18896 hp = hole_head;
- 18897
- 18898 /* If this block's address is numerically less than the lowest hole currently
- 18899 * available, or if no holes are currently available, put this hole on the
- 18900 * front of the hole list.
- 18901 */
- 18902 if (hp == NIL_HOLE || base <= hp->h_base) {
- 18903 /* Block to be freed goes on front of the hole list. */
- 18904 new_ptr->h_next = hp;
- 18905 hole_head = new_ptr;
- 18906 merge(new_ptr);
- 18907 return;
- 18908 }
- 18909
- 18910 /* Block to be returned does not go on front of hole list. */
- 18911 while (hp != NIL_HOLE && base > hp->h_base) {
- 18912 prev_ptr = hp;
- 18913 hp = hp->h_next;
- 18914 }
- 18915
- 18916 /* We found where it goes. Insert block after 'prev_ptr'. */
- 18917 new_ptr->h_next = prev_ptr->h_next;
- 18918 prev_ptr->h_next = new_ptr;
- 18919 merge(prev_ptr); /* sequence is 'prev_ptr', 'new_ptr', 'hp' */
- 18920 }
-
-
- 18923 /*===========================================================================*
- 18924 * del_slot *
- 18925 *===========================================================================*/
- 18926 PRIVATE void del_slot(prev_ptr, hp)
- 18927 register struct hole *prev_ptr; /* pointer to hole entry just ahead of 'hp' */
- 18928 register struct hole *hp; /* pointer to hole entry to be removed */
- 18929 {
- 18930 /* Remove an entry from the hole list. This procedure is called when a
- 18931 * request to allocate memory removes a hole in its entirety, thus reducing
- 18932 * the numbers of holes in memory, and requiring the elimination of one
- 18933 * entry in the hole list.
- 18934 */
- 18935
- 18936 if (hp == hole_head)
- 18937 hole_head = hp->h_next;
- 18938 else
- 18939 prev_ptr->h_next = hp->h_next;
- 18940
- 18941 hp->h_next = free_slots;
- 18942 free_slots = hp;
- 18943 }
-
-
- 18946 /*===========================================================================*
- 18947 * merge *
- 18948 *===========================================================================*/
- 18949 PRIVATE void merge(hp)
- 18950 register struct hole *hp; /* ptr to hole to merge with its successors */
- 18951 {
- 18952 /* Check for contiguous holes and merge any found. Contiguous holes can occur
- 18953 * when a block of memory is freed, and it happens to abut another hole on
- 18954 * either or both ends. The pointer 'hp' points to the first of a series of
- 18955 * three holes that can potentially all be merged together.
- 18956 */
- 18957
- 18958 register struct hole *next_ptr;
- 18959
- 18960 /* If 'hp' points to the last hole, no merging is possible. If it does not,
- 18961 * try to absorb its successor into it and free the successor's table entry.
- 18962 */
- 18963 if ( (next_ptr = hp->h_next) == NIL_HOLE) return;
- 18964 if (hp->h_base + hp->h_len == next_ptr->h_base) {
- 18965 hp->h_len += next_ptr->h_len; /* first one gets second one's mem */
- 18966 del_slot(hp, next_ptr);
- 18967 } else {
- 18968 hp = next_ptr;
- 18969 }
- 18970
- 18971 /* If 'hp' now points to the last hole, return; otherwise, try to absorb its
- 18972 * successor into it.
- 18973 */
- 18974 if ( (next_ptr = hp->h_next) == NIL_HOLE) return;
- 18975 if (hp->h_base + hp->h_len == next_ptr->h_base) {
- 18976 hp->h_len += next_ptr->h_len;
- 18977 del_slot(hp, next_ptr);
- 18978 }
- 18979 }
-
-
- 18982 /*===========================================================================*
- 18983 * max_hole *
- 18984 *===========================================================================*/
- 18985 PUBLIC phys_clicks max_hole()
- 18986 {
- 18987 /* Scan the hole list and return the largest hole. */
- 18988
- 18989 register struct hole *hp;
- 18990 register phys_clicks max;
- 18991
- 18992 hp = hole_head;
- 18993 max = 0;
- 18994 while (hp != NIL_HOLE) {
- 18995 if (hp->h_len > max) max = hp->h_len;
- 18996 hp = hp->h_next;
- 18997 }
- 18998 return(max);
- 18999 }
-
-
- 19002 /*===========================================================================*
- 19003 * mem_init *
- 19004 *===========================================================================*/
- 19005 PUBLIC void mem_init(total, free)
- 19006 phys_clicks *total, *free; /* memory size summaries */
- 19007 {
- 19008 /* Initialize hole lists. There are two lists: 'hole_head' points to a linked
- 19009 * list of all the holes (unused memory) in the system; 'free_slots' points to
- 19010 * a linked list of table entries that are not in use. Initially, the former
- 19011 * list has one entry for each chunk of physical memory, and the second
- 19012 * list links together the remaining table slots. As memory becomes more
- 19013 * fragmented in the course of time (i.e., the initial big holes break up into
- 19014 * smaller holes), new table slots are needed to represent them. These slots
- 19015 * are taken from the list headed by 'free_slots'.
- 19016 */
- 19017
- 19018 register struct hole *hp;
- 19019 phys_clicks base; /* base address of chunk */
- 19020 phys_clicks size; /* size of chunk */
- 19021 message mess;
- 19022
- 19023 /* Put all holes on the free list. */
- 19024 for (hp = &hole[0]; hp < &hole[NR_HOLES]; hp++) hp->h_next = hp + 1;
- 19025 hole[NR_HOLES-1].h_next = NIL_HOLE;
- 19026 hole_head = NIL_HOLE;
- 19027 free_slots = &hole[0];
- 19028
- 19029 /* Ask the kernel for chunks of physical memory and allocate a hole for
- 19030 * each of them. The SYS_MEM call responds with the base and size of the
- 19031 * next chunk and the total amount of memory.
- 19032 */
- 19033 *free = 0;
- 19034 for (;;) {
- 19035 mess.m_type = SYS_MEM;
- 19036 if (sendrec(SYSTASK, &mess) != OK) panic("bad SYS_MEM?", NO_NUM);
- 19037 base = mess.m1_i1;
- 19038 size = mess.m1_i2;
- 19039 if (size == 0) break; /* no more? */
- 19040
- 19041 free_mem(base, size);
- 19042 *total = mess.m1_i3;
- 19043 *free += size;
- 19044 }
- 19045 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/mm/utility.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 19100 /* This file contains some utility routines for MM.
- 19101 *
- 19102 * The entry points are:
- 19103 * allowed: see if an access is permitted
- 19104 * no_sys: this routine is called for invalid system call numbers
- 19105 * panic: MM has run aground of a fatal error and cannot continue
- 19106 * tell_fs: interface to FS
- 19107 */
- 19108
- 19109 #include "mm.h"
- 19110 #include <sys/stat.h>
- 19111 #include <minix/callnr.h>
- 19112 #include <minix/com.h>
- 19113 #include <fcntl.h>
- 19114 #include <signal.h> /* needed only because mproc.h needs it */
- 19115 #include "mproc.h"
- 19116
- 19117 /*===========================================================================*
- 19118 * allowed *
- 19119 *===========================================================================*/
- 19120 PUBLIC int allowed(name_buf, s_buf, mask)
- 19121 char *name_buf; /* pointer to file name to be EXECed */
- 19122 struct stat *s_buf; /* buffer for doing and returning stat struct*/
- 19123 int mask; /* R_BIT, W_BIT, or X_BIT */
- 19124 {
- 19125 /* Check to see if file can be accessed. Return EACCES or ENOENT if the access
- 19126 * is prohibited. If it is legal open the file and return a file descriptor.
- 19127 */
- 19128
- 19129 int fd;
- 19130 int save_errno;
- 19131
- 19132 /* Use the fact that mask for access() is the same as the permissions mask.
- 19133 * E.g., X_BIT in <minix/const.h> is the same as X_OK in <unistd.h> and
- 19134 * S_IXOTH in <sys/stat.h>. tell_fs(DO_CHDIR, ...) has set MM's real ids
- 19135 * to the user's effective ids, so access() works right for setuid programs.
- 19136 */
- 19137 if (access(name_buf, mask) < 0) return(-errno);
- 19138
- 19139 /* The file is accessible but might not be readable. Make it readable. */
- 19140 tell_fs(SETUID, MM_PROC_NR, (int) SUPER_USER, (int) SUPER_USER);
- 19141
- 19142 /* Open the file and fstat it. Restore the ids early to handle errors. */
- 19143 fd = open(name_buf, O_RDONLY);
- 19144 save_errno = errno; /* open might fail, e.g. from ENFILE */
- 19145 tell_fs(SETUID, MM_PROC_NR, (int) mp->mp_effuid, (int) mp->mp_effuid);
- 19146 if (fd < 0) return(-save_errno);
- 19147 if (fstat(fd, s_buf) < 0) panic("allowed: fstat failed", NO_NUM);
- 19148
- 19149 /* Only regular files can be executed. */
- 19150 if (mask == X_BIT && (s_buf->st_mode & I_TYPE) != I_REGULAR) {
- 19151 close(fd);
- 19152 return(EACCES);
- 19153 }
- 19154 return(fd);
- 19155 }
-
-
- 19158 /*===========================================================================*
- 19159 * no_sys *
- 19160 *===========================================================================*/
- 19161 PUBLIC int no_sys()
- 19162 {
- 19163 /* A system call number not implemented by MM has been requested. */
- 19164
- 19165 return(EINVAL);
- 19166 }
-
-
- 19169 /*===========================================================================*
- 19170 * panic *
- 19171 *===========================================================================*/
- 19172 PUBLIC void panic(format, num)
- 19173 char *format; /* format string */
- 19174 int num; /* number to go with format string */
- 19175 {
- 19176 /* Something awful has happened. Panics are caused when an internal
- 19177 * inconsistency is detected, e.g., a programming error or illegal value of a
- 19178 * defined constant.
- 19179 */
- 19180
- 19181 printf("Memory manager panic: %s ", format);
- 19182 if (num != NO_NUM) printf("%d",num);
- 19183 printf("n");
- 19184 tell_fs(SYNC, 0, 0, 0); /* flush the cache to the disk */
- 19185 sys_abort(RBT_PANIC);
- 19186 }
-
-
- 19189 /*===========================================================================*
- 19190 * tell_fs *
- 19191 *===========================================================================*/
- 19192 PUBLIC void tell_fs(what, p1, p2, p3)
- 19193 int what, p1, p2, p3;
- 19194 {
- 19195 /* This routine is only used by MM to inform FS of certain events:
- 19196 * tell_fs(CHDIR, slot, dir, 0)
- 19197 * tell_fs(EXEC, proc, 0, 0)
- 19198 * tell_fs(EXIT, proc, 0, 0)
- 19199 * tell_fs(FORK, parent, child, pid)
- 19200 * tell_fs(SETGID, proc, realgid, effgid)
- 19201 * tell_fs(SETSID, proc, 0, 0)
- 19202 * tell_fs(SETUID, proc, realuid, effuid)
- 19203 * tell_fs(SYNC, 0, 0, 0)
- 19204 * tell_fs(UNPAUSE, proc, signr, 0)
- 19205 */
- 19206
- 19207 message m;
- 19208
- 19209 m.m1_i1 = p1;
- 19210 m.m1_i2 = p2;
- 19211 m.m1_i3 = p3;
- 19212 _taskcall(FS_PROC_NR, what, &m);
- 19213 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/mm/putk.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 19300 /* MM must occasionally print some message. It uses the standard library
- 19301 * routine printk(). (The name "printf" is really a macro defined as
- 19302 * "printk"). Printing is done by calling the TTY task directly, not going
- 19303 * through FS.
- 19304 */
- 19305
- 19306 #include "mm.h"
- 19307 #include <minix/com.h>
- 19308
- 19309 #define BUF_SIZE 100 /* print buffer size */
- 19310
- 19311 PRIVATE int buf_count; /* # characters in the buffer */
- 19312 PRIVATE char print_buf[BUF_SIZE]; /* output is buffered here */
- 19313 PRIVATE message putch_msg; /* used for message to TTY task */
- 19314
- 19315 _PROTOTYPE( FORWARD void flush, (void) );
- 19316
- 19317 /*===========================================================================*
- 19318 * putk *
- 19319 *===========================================================================*/
- 19320 PUBLIC void putk(c)
- 19321 int c;
- 19322 {
- 19323 /* Accumulate another character. If 0 or buffer full, print it. */
- 19324
- 19325 if (c == 0 || buf_count == BUF_SIZE) flush();
- 19326 if (c == 'n') putk('r');
- 19327 if (c != 0) print_buf[buf_count++] = c;
- 19328 }
-
-
- 19331 /*===========================================================================*
- 19332 * flush *
- 19333 *===========================================================================*/
- 19334 PRIVATE void flush()
- 19335 {
- 19336 /* Flush the print buffer by calling TTY task. */
- 19337
- 19338 if (buf_count == 0) return;
- 19339 putch_msg.m_type = DEV_WRITE;
- 19340 putch_msg.PROC_NR = 0;
- 19341 putch_msg.TTY_LINE = 0;
- 19342 putch_msg.ADDRESS = print_buf;
- 19343 putch_msg.COUNT = buf_count;
- 19344 sendrec(TTY, &putch_msg);
- 19345 buf_count = 0;
- 19346 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/fs.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 19400 /* This is the master header for fs. It includes some other files
- 19401 * and defines the principal constants.
- 19402 */
- 19403 #define _POSIX_SOURCE 1 /* tell headers to include POSIX stuff */
- 19404 #define _MINIX 1 /* tell headers to include MINIX stuff */
- 19405 #define _SYSTEM 1 /* tell headers that this is the kernel */
- 19406
- 19407 /* The following are so basic, all the *.c files get them automatically. */
- 19408 #include <minix/config.h> /* MUST be first */
- 19409 #include <ansi.h> /* MUST be second */
- 19410 #include <sys/types.h>
- 19411 #include <minix/const.h>
- 19412 #include <minix/type.h>
- 19413
- 19414 #include <limits.h>
- 19415 #include <errno.h>
- 19416
- 19417 #include <minix/syslib.h>
- 19418
- 19419 #include "const.h"
- 19420 #include "type.h"
- 19421 #include "proto.h"
- 19422 #include "glo.h"
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/const.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 19500 /* Tables sizes */
- 19501 #define V1_NR_DZONES 7 /* # direct zone numbers in a V1 inode */
- 19502 #define V1_NR_TZONES 9 /* total # zone numbers in a V1 inode */
- 19503 #define V2_NR_DZONES 7 /* # direct zone numbers in a V2 inode */
- 19504 #define V2_NR_TZONES 10 /* total # zone numbers in a V2 inode */
- 19505
- 19506 #define NR_FILPS 128 /* # slots in filp table */
- 19507 #define NR_INODES 64 /* # slots in "in core" inode table */
- 19508 #define NR_SUPERS 8 /* # slots in super block table */
- 19509 #define NR_LOCKS 8 /* # slots in the file locking table */
- 19510
- 19511 /* The type of sizeof may be (unsigned) long. Use the following macro for
- 19512 * taking the sizes of small objects so that there are no surprises like
- 19513 * (small) long constants being passed to routines expecting an int.
- 19514 */
- 19515 #define usizeof(t) ((unsigned) sizeof(t))
- 19516
- 19517 /* File system types. */
- 19518 #define SUPER_MAGIC 0x137F /* magic number contained in super-block */
- 19519 #define SUPER_REV 0x7F13 /* magic # when 68000 disk read on PC or vv */
- 19520 #define SUPER_V2 0x2468 /* magic # for V2 file systems */
- 19521 #define SUPER_V2_REV 0x6824 /* V2 magic written on PC, read on 68K or vv */
- 19522
- 19523 #define V1 1 /* version number of V1 file systems */
- 19524 #define V2 2 /* version number of V2 file systems */
- 19525
- 19526 /* Miscellaneous constants */
- 19527 #define SU_UID ((uid_t) 0) /* super_user's uid_t */
- 19528 #define SYS_UID ((uid_t) 0) /* uid_t for processes MM and INIT */
- 19529 #define SYS_GID ((gid_t) 0) /* gid_t for processes MM and INIT */
- 19530 #define NORMAL 0 /* forces get_block to do disk read */
- 19531 #define NO_READ 1 /* prevents get_block from doing disk read */
- 19532 #define PREFETCH 2 /* tells get_block not to read or mark dev */
- 19533
- 19534 #define XPIPE (-NR_TASKS-1) /* used in fp_task when susp'd on pipe */
- 19535 #define XOPEN (-NR_TASKS-2) /* used in fp_task when susp'd on open */
- 19536 #define XLOCK (-NR_TASKS-3) /* used in fp_task when susp'd on lock */
- 19537 #define XPOPEN (-NR_TASKS-4) /* used in fp_task when susp'd on pipe open */
- 19538
- 19539 #define NO_BIT ((bit_t) 0) /* returned by alloc_bit() to signal failure */
- 19540
- 19541 #define DUP_MASK 0100 /* mask to distinguish dup2 from dup */
- 19542
- 19543 #define LOOK_UP 0 /* tells search_dir to lookup string */
- 19544 #define ENTER 1 /* tells search_dir to make dir entry */
- 19545 #define DELETE 2 /* tells search_dir to delete entry */
- 19546 #define IS_EMPTY 3 /* tells search_dir to ret. OK or ENOTEMPTY */
- 19547
- 19548 #define CLEAN 0 /* disk and memory copies identical */
- 19549 #define DIRTY 1 /* disk and memory copies differ */
- 19550 #define ATIME 002 /* set if atime field needs updating */
- 19551 #define CTIME 004 /* set if ctime field needs updating */
- 19552 #define MTIME 010 /* set if mtime field needs updating */
- 19553
- 19554 #define BYTE_SWAP 0 /* tells conv2/conv4 to swap bytes */
- 19555 #define DONT_SWAP 1 /* tells conv2/conv4 not to swap bytes */
- 19556
- 19557 #define END_OF_FILE (-104) /* eof detected */
- 19558
- 19559 #define ROOT_INODE 1 /* inode number for root directory */
- 19560 #define BOOT_BLOCK ((block_t) 0) /* block number of boot block */
- 19561 #define SUPER_BLOCK ((block_t) 1) /* block number of super block */
- 19562
- 19563 #define DIR_ENTRY_SIZE usizeof (struct direct) /* # bytes/dir entry */
- 19564 #define NR_DIR_ENTRIES (BLOCK_SIZE/DIR_ENTRY_SIZE) /* # dir entries/blk */
- 19565 #define SUPER_SIZE usizeof (struct super_block) /* super_block size */
- 19566 #define PIPE_SIZE (V1_NR_DZONES*BLOCK_SIZE) /* pipe size in bytes */
- 19567 #define BITMAP_CHUNKS (BLOCK_SIZE/usizeof (bitchunk_t))/* # map chunks/blk */
- 19568
- 19569 /* Derived sizes pertaining to the V1 file system. */
- 19570 #define V1_ZONE_NUM_SIZE usizeof (zone1_t) /* # bytes in V1 zone */
- 19571 #define V1_INODE_SIZE usizeof (d1_inode) /* bytes in V1 dsk ino */
- 19572 #define V1_INDIRECTS (BLOCK_SIZE/V1_ZONE_NUM_SIZE) /* # zones/indir block */
- 19573 #define V1_INODES_PER_BLOCK (BLOCK_SIZE/V1_INODE_SIZE)/* # V1 dsk inodes/blk */
- 19574
- 19575 /* Derived sizes pertaining to the V2 file system. */
- 19576 #define V2_ZONE_NUM_SIZE usizeof (zone_t) /* # bytes in V2 zone */
- 19577 #define V2_INODE_SIZE usizeof (d2_inode) /* bytes in V2 dsk ino */
- 19578 #define V2_INDIRECTS (BLOCK_SIZE/V2_ZONE_NUM_SIZE) /* # zones/indir block */
- 19579 #define V2_INODES_PER_BLOCK (BLOCK_SIZE/V2_INODE_SIZE)/* # V2 dsk inodes/blk */
- 19580
- 19581 #define printf printk
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/type.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 19600 /* Declaration of the V1 inode as it is on the disk (not in core). */
- 19601 typedef struct { /* V1.x disk inode */
- 19602 mode_t d1_mode; /* file type, protection, etc. */
- 19603 uid_t d1_uid; /* user id of the file's owner */
- 19604 off_t d1_size; /* current file size in bytes */
- 19605 time_t d1_mtime; /* when was file data last changed */
- 19606 gid_t d1_gid; /* group number */
- 19607 nlink_t d1_nlinks; /* how many links to this file */
- 19608 u16_t d1_zone[V1_NR_TZONES]; /* block nums for direct, ind, and dbl ind */
- 19609 } d1_inode;
- 19610
- 19611 /* Declaration of the V2 inode as it is on the disk (not in core). */
- 19612 typedef struct { /* V2.x disk inode */
- 19613 mode_t d2_mode; /* file type, protection, etc. */
- 19614 u16_t d2_nlinks; /* how many links to this file. HACK! */
- 19615 uid_t d2_uid; /* user id of the file's owner. */
- 19616 u16_t d2_gid; /* group number HACK! */
- 19617 off_t d2_size; /* current file size in bytes */
- 19618 time_t d2_atime; /* when was file data last accessed */
- 19619 time_t d2_mtime; /* when was file data last changed */
- 19620 time_t d2_ctime; /* when was inode data last changed */
- 19621 zone_t d2_zone[V2_NR_TZONES]; /* block nums for direct, ind, and dbl ind */
- 19622 } d2_inode;
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/proto.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 19700 /* Function prototypes. */
- 19701
- 19702 /* Structs used in prototypes must be declared as such first. */
- 19703 struct buf;
- 19704 struct filp;
- 19705 struct inode;
- 19706 struct super_block;
- 19707
- 19708 /* cache.c */
- 19709 _PROTOTYPE( zone_t alloc_zone, (Dev_t dev, zone_t z) );
- 19710 _PROTOTYPE( void flushall, (Dev_t dev) );
- 19711 _PROTOTYPE( void free_zone, (Dev_t dev, zone_t numb) );
- 19712 _PROTOTYPE( struct buf *get_block, (Dev_t dev, block_t block,int only_search));
- 19713 _PROTOTYPE( void invalidate, (Dev_t device) );
- 19714 _PROTOTYPE( void put_block, (struct buf *bp, int block_type) );
- 19715 _PROTOTYPE( void rw_block, (struct buf *bp, int rw_flag) );
- 19716 _PROTOTYPE( void rw_scattered, (Dev_t dev,
- 19717 struct buf **bufq, int bufqsize, int rw_flag) );
- 19718
- 19719 /* device.c */
- 19720 _PROTOTYPE( void call_task, (int task_nr, message *mess_ptr) );
- 19721 _PROTOTYPE( void dev_opcl, (int task_nr, message *mess_ptr) );
- 19722 _PROTOTYPE( int dev_io, (int rw_flag, int nonblock, Dev_t dev,
- 19723 off_t pos, int bytes, int proc, char *buff) );
- 19724 _PROTOTYPE( int do_ioctl, (void) );
- 19725 _PROTOTYPE( void no_dev, (int task_nr, message *m_ptr) );
- 19726 _PROTOTYPE( void call_ctty, (int task_nr, message *mess_ptr) );
- 19727 _PROTOTYPE( void tty_open, (int task_nr, message *mess_ptr) );
- 19728 _PROTOTYPE( void ctty_close, (int task_nr, message *mess_ptr) );
- 19729 _PROTOTYPE( void ctty_open, (int task_nr, message *mess_ptr) );
- 19730 _PROTOTYPE( int do_setsid, (void) );
- 19731 #if ENABLE_NETWORKING
- 19732 _PROTOTYPE( void net_open, (int task_nr, message *mess_ptr) );
- 19733 #else
- 19734 #define net_open 0
- 19735 #endif
- 19736
- 19737 /* filedes.c */
- 19738 _PROTOTYPE( struct filp *find_filp, (struct inode *rip, Mode_t bits) );
- 19739 _PROTOTYPE( int get_fd, (int start, Mode_t bits, int *k, struct filp **fpt) );
- 19740 _PROTOTYPE( struct filp *get_filp, (int fild) );
- 19741
- 19742 /* inode.c */
- 19743 _PROTOTYPE( struct inode *alloc_inode, (Dev_t dev, Mode_t bits) );
- 19744 _PROTOTYPE( void dup_inode, (struct inode *ip) );
- 19745 _PROTOTYPE( void free_inode, (Dev_t dev, Ino_t numb) );
- 19746 _PROTOTYPE( struct inode *get_inode, (Dev_t dev, int numb) );
- 19747 _PROTOTYPE( void put_inode, (struct inode *rip) );
- 19748 _PROTOTYPE( void update_times, (struct inode *rip) );
- 19749 _PROTOTYPE( void rw_inode, (struct inode *rip, int rw_flag) );
- 19750 _PROTOTYPE( void wipe_inode, (struct inode *rip) );
- 19751
- 19752 /* link.c */
- 19753 _PROTOTYPE( int do_link, (void) );
- 19754 _PROTOTYPE( int do_unlink, (void) );
- 19755 _PROTOTYPE( int do_rename, (void) );
- 19756 _PROTOTYPE( void truncate, (struct inode *rip) );
- 19757
- 19758 /* lock.c */
- 19759 _PROTOTYPE( int lock_op, (struct filp *f, int req) );
- 19760 _PROTOTYPE( void lock_revive, (void) );
- 19761
- 19762 /* main.c */
- 19763 _PROTOTYPE( void main, (void) );
- 19764 _PROTOTYPE( void reply, (int whom, int result) );
- 19765
- 19766 /* misc.c */
- 19767 _PROTOTYPE( int do_dup, (void) );
- 19768 _PROTOTYPE( int do_exit, (void) );
- 19769 _PROTOTYPE( int do_fcntl, (void) );
- 19770 _PROTOTYPE( int do_fork, (void) );
- 19771 _PROTOTYPE( int do_exec, (void) );
- 19772 _PROTOTYPE( int do_revive, (void) );
- 19773 _PROTOTYPE( int do_set, (void) );
- 19774 _PROTOTYPE( int do_sync, (void) );
- 19775
- 19776 /* mount.c */
- 19777 _PROTOTYPE( int do_mount, (void) );
- 19778 _PROTOTYPE( int do_umount, (void) );
- 19779
- 19780 /* open.c */
- 19781 _PROTOTYPE( int do_close, (void) );
- 19782 _PROTOTYPE( int do_creat, (void) );
- 19783 _PROTOTYPE( int do_lseek, (void) );
- 19784 _PROTOTYPE( int do_mknod, (void) );
- 19785 _PROTOTYPE( int do_mkdir, (void) );
- 19786 _PROTOTYPE( int do_open, (void) );
- 19787
- 19788 /* path.c */
- 19789 _PROTOTYPE( struct inode *advance,(struct inode *dirp, char string[NAME_MAX]));
- 19790 _PROTOTYPE( int search_dir, (struct inode *ldir_ptr,
- 19791 char string [NAME_MAX], ino_t *numb, int flag) );
- 19792 _PROTOTYPE( struct inode *eat_path, (char *path) );
- 19793 _PROTOTYPE( struct inode *last_dir, (char *path, char string [NAME_MAX]));
- 19794
- 19795 /* pipe.c */
- 19796 _PROTOTYPE( int do_pipe, (void) );
- 19797 _PROTOTYPE( int do_unpause, (void) );
- 19798 _PROTOTYPE( int pipe_check, (struct inode *rip, int rw_flag,
- 19799 int oflags, int bytes, off_t position, int *canwrite));
- 19800 _PROTOTYPE( void release, (struct inode *ip, int call_nr, int count) );
- 19801 _PROTOTYPE( void revive, (int proc_nr, int bytes) );
- 19802 _PROTOTYPE( void suspend, (int task) );
- 19803
- 19804 /* protect.c */
- 19805 _PROTOTYPE( int do_access, (void) );
- 19806 _PROTOTYPE( int do_chmod, (void) );
- 19807 _PROTOTYPE( int do_chown, (void) );
- 19808 _PROTOTYPE( int do_umask, (void) );
- 19809 _PROTOTYPE( int forbidden, (struct inode *rip, Mode_t access_desired) );
- 19810 _PROTOTYPE( int read_only, (struct inode *ip) );
- 19811
- 19812 /* putk.c */
- 19813 _PROTOTYPE( void putk, (int c) );
- 19814
- 19815 /* read.c */
- 19816 _PROTOTYPE( int do_read, (void) );
- 19817 _PROTOTYPE( struct buf *rahead, (struct inode *rip, block_t baseblock,
- 19818 off_t position, unsigned bytes_ahead) );
- 19819 _PROTOTYPE( void read_ahead, (void) );
- 19820 _PROTOTYPE( block_t read_map, (struct inode *rip, off_t position) );
- 19821 _PROTOTYPE( int read_write, (int rw_flag) );
- 19822 _PROTOTYPE( zone_t rd_indir, (struct buf *bp, int index) );
- 19823
- 19824 /* stadir.c */
- 19825 _PROTOTYPE( int do_chdir, (void) );
- 19826 _PROTOTYPE( int do_chroot, (void) );
- 19827 _PROTOTYPE( int do_fstat, (void) );
- 19828 _PROTOTYPE( int do_stat, (void) );
- 19829
- 19830 /* super.c */
- 19831 _PROTOTYPE( bit_t alloc_bit, (struct super_block *sp, int map, bit_t origin));
- 19832 _PROTOTYPE( void free_bit, (struct super_block *sp, int map,
- 19833 bit_t bit_returned) );
- 19834 _PROTOTYPE( struct super_block *get_super, (Dev_t dev) );
- 19835 _PROTOTYPE( int mounted, (struct inode *rip) );
- 19836 _PROTOTYPE( int read_super, (struct super_block *sp) );
- 19837
- 19838 /* time.c */
- 19839 _PROTOTYPE( int do_stime, (void) );
- 19840 _PROTOTYPE( int do_time, (void) );
- 19841 _PROTOTYPE( int do_tims, (void) );
- 19842 _PROTOTYPE( int do_utime, (void) );
- 19843
- 19844 /* utility.c */
- 19845 _PROTOTYPE( time_t clock_time, (void) );
- 19846 _PROTOTYPE( unsigned conv2, (int norm, int w) );
- 19847 _PROTOTYPE( long conv4, (int norm, long x) );
- 19848 _PROTOTYPE( int fetch_name, (char *path, int len, int flag) );
- 19849 _PROTOTYPE( int no_sys, (void) );
- 19850 _PROTOTYPE( void panic, (char *format, int num) );
- 19851
- 19852 /* write.c */
- 19853 _PROTOTYPE( void clear_zone, (struct inode *rip, off_t pos, int flag) );
- 19854 _PROTOTYPE( int do_write, (void) );
- 19855 _PROTOTYPE( struct buf *new_block, (struct inode *rip, off_t position) );
- 19856 _PROTOTYPE( void zero_block, (struct buf *bp) );
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/glo.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 19900 /* EXTERN should be extern except for the table file */
- 19901 #ifdef _TABLE
- 19902 #undef EXTERN
- 19903 #define EXTERN
- 19904 #endif
- 19905
- 19906 /* File System global variables */
- 19907 EXTERN struct fproc *fp; /* pointer to caller's fproc struct */
- 19908 EXTERN int super_user; /* 1 if caller is super_user, else 0 */
- 19909 EXTERN int dont_reply; /* normally 0; set to 1 to inhibit reply */
- 19910 EXTERN int susp_count; /* number of procs suspended on pipe */
- 19911 EXTERN int nr_locks; /* number of locks currently in place */
- 19912 EXTERN int reviving; /* number of pipe processes to be revived */
- 19913 EXTERN off_t rdahedpos; /* position to read ahead */
- 19914 EXTERN struct inode *rdahed_inode; /* pointer to inode to read ahead */
- 19915
- 19916 /* The parameters of the call are kept here. */
- 19917 EXTERN message m; /* the input message itself */
- 19918 EXTERN message m1; /* the output message used for reply */
- 19919 EXTERN int who; /* caller's proc number */
- 19920 EXTERN int fs_call; /* system call number */
- 19921 EXTERN char user_path[PATH_MAX];/* storage for user path name */
- 19922
- 19923 /* The following variables are used for returning results to the caller. */
- 19924 EXTERN int err_code; /* temporary storage for error number */
- 19925 EXTERN int rdwt_err; /* status of last disk i/o request */
- 19926
- 19927 /* Data which need initialization. */
- 19928 extern _PROTOTYPE (int (*call_vector[]), (void) ); /* sys call table */
- 19929 extern int max_major; /* maximum major device (+ 1) */
- 19930 extern char dot1[2]; /* dot1 (&dot1[0]) and dot2 (&dot2[0]) have a special */
- 19931 extern char dot2[3]; /* meaning to search_dir: no access permission check. */
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/fproc.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 20000 /* This is the per-process information. A slot is reserved for each potential
- 20001 * process. Thus NR_PROCS must be the same as in the kernel. It is not possible
- 20002 * or even necessary to tell when a slot is free here.
- 20003 */
- 20004
- 20005
- 20006 EXTERN struct fproc {
- 20007 mode_t fp_umask; /* mask set by umask system call */
- 20008 struct inode *fp_workdir; /* pointer to working directory's inode */
- 20009 struct inode *fp_rootdir; /* pointer to current root dir (see chroot) */
- 20010 struct filp *fp_filp[OPEN_MAX];/* the file descriptor table */
- 20011 uid_t fp_realuid; /* real user id */
- 20012 uid_t fp_effuid; /* effective user id */
- 20013 gid_t fp_realgid; /* real group id */
- 20014 gid_t fp_effgid; /* effective group id */
- 20015 dev_t fp_tty; /* major/minor of controlling tty */
- 20016 int fp_fd; /* place to save fd if rd/wr can't finish */
- 20017 char *fp_buffer; /* place to save buffer if rd/wr can't finish*/
- 20018 int fp_nbytes; /* place to save bytes if rd/wr can't finish */
- 20019 int fp_cum_io_partial; /* partial byte count if rd/wr can't finish */
- 20020 char fp_suspended; /* set to indicate process hanging */
- 20021 char fp_revived; /* set to indicate process being revived */
- 20022 char fp_task; /* which task is proc suspended on */
- 20023 char fp_sesldr; /* true if proc is a session leader */
- 20024 pid_t fp_pid; /* process id */
- 20025 long fp_cloexec; /* bit map for POSIX Table 6-2 FD_CLOEXEC */
- 20026 } fproc[NR_PROCS];
- 20027
- 20028 /* Field values. */
- 20029 #define NOT_SUSPENDED 0 /* process is not suspended on pipe or task */
- 20030 #define SUSPENDED 1 /* process is suspended on pipe or task */
- 20031 #define NOT_REVIVING 0 /* process is not being revived */
- 20032 #define REVIVING 1 /* process is being revived from suspension */
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/buf.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 20100 /* Buffer (block) cache. To acquire a block, a routine calls get_block(),
- 20101 * telling which block it wants. The block is then regarded as "in use"
- 20102 * and has its 'b_count' field incremented. All the blocks that are not
- 20103 * in use are chained together in an LRU list, with 'front' pointing
- 20104 * to the least recently used block, and 'rear' to the most recently used
- 20105 * block. A reverse chain, using the field b_prev is also maintained.
- 20106 * Usage for LRU is measured by the time the put_block() is done. The second
- 20107 * parameter to put_block() can violate the LRU order and put a block on the
- 20108 * front of the list, if it will probably not be needed soon. If a block
- 20109 * is modified, the modifying routine must set b_dirt to DIRTY, so the block
- 20110 * will eventually be rewritten to the disk.
- 20111 */
- 20112
- 20113 #include <sys/dir.h> /* need struct direct */
- 20114
- 20115 EXTERN struct buf {
- 20116 /* Data portion of the buffer. */
- 20117 union {
- 20118 char b__data[BLOCK_SIZE]; /* ordinary user data */
- 20119 struct direct b__dir[NR_DIR_ENTRIES]; /* directory block */
- 20120 zone1_t b__v1_ind[V1_INDIRECTS]; /* V1 indirect block */
- 20121 zone_t b__v2_ind[V2_INDIRECTS]; /* V2 indirect block */
- 20122 d1_inode b__v1_ino[V1_INODES_PER_BLOCK]; /* V1 inode block */
- 20123 d2_inode b__v2_ino[V2_INODES_PER_BLOCK]; /* V2 inode block */
- 20124 bitchunk_t b__bitmap[BITMAP_CHUNKS]; /* bit map block */
- 20125 } b;
- 20126
- 20127 /* Header portion of the buffer. */
- 20128 struct buf *b_next; /* used to link all free bufs in a chain */
- 20129 struct buf *b_prev; /* used to link all free bufs the other way */
- 20130 struct buf *b_hash; /* used to link bufs on hash chains */
- 20131 block_t b_blocknr; /* block number of its (minor) device */
- 20132 dev_t b_dev; /* major | minor device where block resides */
- 20133 char b_dirt; /* CLEAN or DIRTY */
- 20134 char b_count; /* number of users of this buffer */
- 20135 } buf[NR_BUFS];
- 20136
- 20137 /* A block is free if b_dev == NO_DEV. */
- 20138
- 20139 #define NIL_BUF ((struct buf *) 0) /* indicates absence of a buffer */
- 20140
- 20141 /* These defs make it possible to use to bp->b_data instead of bp->b.b__data */
- 20142 #define b_data b.b__data
- 20143 #define b_dir b.b__dir
- 20144 #define b_v1_ind b.b__v1_ind
- 20145 #define b_v2_ind b.b__v2_ind
- 20146 #define b_v1_ino b.b__v1_ino
- 20147 #define b_v2_ino b.b__v2_ino
- 20148 #define b_bitmap b.b__bitmap
- 20149
- 20150 EXTERN struct buf *buf_hash[NR_BUF_HASH]; /* the buffer hash table */
- 20151
- 20152 EXTERN struct buf *front; /* points to least recently used free block */
- 20153 EXTERN struct buf *rear; /* points to most recently used free block */
- 20154 EXTERN int bufs_in_use; /* # bufs currently in use (not on free list)*/
- 20155
- 20156 /* When a block is released, the type of usage is passed to put_block(). */
- 20157 #define WRITE_IMMED 0100 /* block should be written to disk now */
- 20158 #define ONE_SHOT 0200 /* set if block not likely to be needed soon */
- 20159
- 20160 #define INODE_BLOCK (0 + MAYBE_WRITE_IMMED) /* inode block */
- 20161 #define DIRECTORY_BLOCK (1 + MAYBE_WRITE_IMMED) /* directory block */
- 20162 #define INDIRECT_BLOCK (2 + MAYBE_WRITE_IMMED) /* pointer block */
- 20163 #define MAP_BLOCK (3 + MAYBE_WRITE_IMMED) /* bit map */
- 20164 #define ZUPER_BLOCK (4 + WRITE_IMMED + ONE_SHOT) /* super block */
- 20165 #define FULL_DATA_BLOCK 5 /* data, fully used */
- 20166 #define PARTIAL_DATA_BLOCK 6 /* data, partly used*/
- 20167
- 20168 #define HASH_MASK (NR_BUF_HASH - 1) /* mask for hashing block numbers */
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/dev.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 20200 /* Device table. This table is indexed by major device number. It provides
- 20201 * the link between major device numbers and the routines that process them.
- 20202 */
- 20203
- 20204 typedef _PROTOTYPE (void (*dmap_t), (int task, message *m_ptr) );
- 20205
- 20206 extern struct dmap {
- 20207 dmap_t dmap_open;
- 20208 dmap_t dmap_rw;
- 20209 dmap_t dmap_close;
- 20210 int dmap_task;
- 20211 } dmap[];
- 20212
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/file.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 20300 /* This is the filp table. It is an intermediary between file descriptors and
- 20301 * inodes. A slot is free if filp_count == 0.
- 20302 */
- 20303
- 20304 EXTERN struct filp {
- 20305 mode_t filp_mode; /* RW bits, telling how file is opened */
- 20306 int filp_flags; /* flags from open and fcntl */
- 20307 int filp_count; /* how many file descriptors share this slot?*/
- 20308 struct inode *filp_ino; /* pointer to the inode */
- 20309 off_t filp_pos; /* file position */
- 20310 } filp[NR_FILPS];
- 20311
- 20312 #define FILP_CLOSED 0 /* filp_mode: associated device closed */
- 20313
- 20314 #define NIL_FILP (struct filp *) 0 /* indicates absence of a filp slot */
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/lock.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 20400 /* This is the file locking table. Like the filp table, it points to the
- 20401 * inode table, however, in this case to achieve advisory locking.
- 20402 */
- 20403 EXTERN struct file_lock {
- 20404 short lock_type; /* F_RDLOCK or F_WRLOCK; 0 means unused slot */
- 20405 pid_t lock_pid; /* pid of the process holding the lock */
- 20406 struct inode *lock_inode; /* pointer to the inode locked */
- 20407 off_t lock_first; /* offset of first byte locked */
- 20408 off_t lock_last; /* offset of last byte locked */
- 20409 } file_lock[NR_LOCKS];
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/inode.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 20500 /* Inode table. This table holds inodes that are currently in use. In some
- 20501 * cases they have been opened by an open() or creat() system call, in other
- 20502 * cases the file system itself needs the inode for one reason or another,
- 20503 * such as to search a directory for a path name.
- 20504 * The first part of the struct holds fields that are present on the
- 20505 * disk; the second part holds fields not present on the disk.
- 20506 * The disk inode part is also declared in "type.h" as 'd1_inode' for V1
- 20507 * file systems and 'd2_inode' for V2 file systems.
- 20508 */
- 20509
- 20510 EXTERN struct inode {
- 20511 mode_t i_mode; /* file type, protection, etc. */
- 20512 nlink_t i_nlinks; /* how many links to this file */
- 20513 uid_t i_uid; /* user id of the file's owner */
- 20514 gid_t i_gid; /* group number */
- 20515 off_t i_size; /* current file size in bytes */
- 20516 time_t i_atime; /* time of last access (V2 only) */
- 20517 time_t i_mtime; /* when was file data last changed */
- 20518 time_t i_ctime; /* when was inode itself changed (V2 only)*/
- 20519 zone_t i_zone[V2_NR_TZONES]; /* zone numbers for direct, ind, and dbl ind */
- 20520
- 20521 /* The following items are not present on the disk. */
- 20522 dev_t i_dev; /* which device is the inode on */
- 20523 ino_t i_num; /* inode number on its (minor) device */
- 20524 int i_count; /* # times inode used; 0 means slot is free */
- 20525 int i_ndzones; /* # direct zones (Vx_NR_DZONES) */
- 20526 int i_nindirs; /* # indirect zones per indirect block */
- 20527 struct super_block *i_sp; /* pointer to super block for inode's device */
- 20528 char i_dirt; /* CLEAN or DIRTY */
- 20529 char i_pipe; /* set to I_PIPE if pipe */
- 20530 char i_mount; /* this bit is set if file mounted on */
- 20531 char i_seek; /* set on LSEEK, cleared on READ/WRITE */
- 20532 char i_update; /* the ATIME, CTIME, and MTIME bits are here */
- 20533 } inode[NR_INODES];
- 20534
- 20535
- 20536 #define NIL_INODE (struct inode *) 0 /* indicates absence of inode slot */
- 20537
- 20538 /* Field values. Note that CLEAN and DIRTY are defined in "const.h" */
- 20539 #define NO_PIPE 0 /* i_pipe is NO_PIPE if inode is not a pipe */
- 20540 #define I_PIPE 1 /* i_pipe is I_PIPE if inode is a pipe */
- 20541 #define NO_MOUNT 0 /* i_mount is NO_MOUNT if file not mounted on*/
- 20542 #define I_MOUNT 1 /* i_mount is I_MOUNT if file mounted on */
- 20543 #define NO_SEEK 0 /* i_seek = NO_SEEK if last op was not SEEK */
- 20544 #define ISEEK 1 /* i_seek = ISEEK if last op was SEEK */
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/param.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 20600 /* The following names are synonyms for the variables in the input message. */
- 20601 #define acc_time m.m2_l1
- 20602 #define addr m.m1_i3
- 20603 #define buffer m.m1_p1
- 20604 #define child m.m1_i2
- 20605 #define co_mode m.m1_i1
- 20606 #define eff_grp_id m.m1_i3
- 20607 #define eff_user_id m.m1_i3
- 20608 #define erki m.m1_p1
- 20609 #define fd m.m1_i1
- 20610 #define fd2 m.m1_i2
- 20611 #define ioflags m.m1_i3
- 20612 #define group m.m1_i3
- 20613 #define real_grp_id m.m1_i2
- 20614 #define ls_fd m.m2_i1
- 20615 #define mk_mode m.m1_i2
- 20616 #define mode m.m3_i2
- 20617 #define c_mode m.m1_i3
- 20618 #define c_name m.m1_p1
- 20619 #define name m.m3_p1
- 20620 #define name1 m.m1_p1
- 20621 #define name2 m.m1_p2
- 20622 #define name_length m.m3_i1
- 20623 #define name1_length m.m1_i1
- 20624 #define name2_length m.m1_i2
- 20625 #define nbytes m.m1_i2
- 20626 #define offset m.m2_l1
- 20627 #define owner m.m1_i2
- 20628 #define parent m.m1_i1
- 20629 #define pathname m.m3_ca1
- 20630 #define pid m.m1_i3
- 20631 #define pro m.m1_i1
- 20632 #define rd_only m.m1_i3
- 20633 #define real_user_id m.m1_i2
- 20634 #define request m.m1_i2
- 20635 #define sig m.m1_i2
- 20636 #define slot1 m.m1_i1
- 20637 #define tp m.m2_l1
- 20638 #define utime_actime m.m2_l1
- 20639 #define utime_modtime m.m2_l2
- 20640 #define utime_file m.m2_p1
- 20641 #define utime_length m.m2_i1
- 20642 #define whence m.m2_i2
- 20643
- 20644 /* The following names are synonyms for the variables in the output message. */
- 20645 #define reply_type m1.m_type
- 20646 #define reply_l1 m1.m2_l1
- 20647 #define reply_i1 m1.m1_i1
- 20648 #define reply_i2 m1.m1_i2
- 20649 #define reply_t1 m1.m4_l1
- 20650 #define reply_t2 m1.m4_l2
- 20651 #define reply_t3 m1.m4_l3
- 20652 #define reply_t4 m1.m4_l4
- 20653 #define reply_t5 m1.m4_l5
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/super.h
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 20700 /* Super block table. The root file system and every mounted file system
- 20701 * has an entry here. The entry holds information about the sizes of the bit
- 20702 * maps and inodes. The s_ninodes field gives the number of inodes available
- 20703 * for files and directories, including the root directory. Inode 0 is
- 20704 * on the disk, but not used. Thus s_ninodes = 4 means that 5 bits will be
- 20705 * used in the bit map, bit 0, which is always 1 and not used, and bits 1-4
- 20706 * for files and directories. The disk layout is:
- 20707 *
- 20708 * Item # blocks
- 20709 * boot block 1
- 20710 * super block 1
- 20711 * inode map s_imap_blocks
- 20712 * zone map s_zmap_blocks
- 20713 * inodes (s_ninodes + 'inodes per block' - 1)/'inodes per block'
- 20714 * unused whatever is needed to fill out the current zone
- 20715 * data zones (s_zones - s_firstdatazone) << s_log_zone_size
- 20716 *
- 20717 * A super_block slot is free if s_dev == NO_DEV.
- 20718 */
- 20719
- 20720
- 20721 EXTERN struct super_block {
- 20722 ino_t s_ninodes; /* # usable inodes on the minor device */
- 20723 zone1_t s_nzones; /* total device size, including bit maps etc */
- 20724 short s_imap_blocks; /* # of blocks used by inode bit map */
- 20725 short s_zmap_blocks; /* # of blocks used by zone bit map */
- 20726 zone1_t s_firstdatazone; /* number of first data zone */
- 20727 short s_log_zone_size; /* log2 of blocks/zone */
- 20728 off_t s_max_size; /* maximum file size on this device */
- 20729 short s_magic; /* magic number to recognize super-blocks */
- 20730 short s_pad; /* try to avoid compiler-dependent padding */
- 20731 zone_t s_zones; /* number of zones (replaces s_nzones in V2) */
- 20732
- 20733 /* The following items are only used when the super_block is in memory. */
- 20734 struct inode *s_isup; /* inode for root dir of mounted file sys */
- 20735 struct inode *s_imount; /* inode mounted on */
- 20736 unsigned s_inodes_per_block; /* precalculated from magic number */
- 20737 dev_t s_dev; /* whose super block is this? */
- 20738 int s_rd_only; /* set to 1 iff file sys mounted read only */
- 20739 int s_native; /* set to 1 iff not byte swapped file system */
- 20740 int s_version; /* file system version, zero means bad magic */
- 20741 int s_ndzones; /* # direct zones in an inode */
- 20742 int s_nindirs; /* # indirect zones per indirect block */
- 20743 bit_t s_isearch; /* inodes below this bit number are in use */
- 20744 bit_t s_zsearch; /* all zones below this bit number are in use*/
- 20745 } super_block[NR_SUPERS];
- 20746
- 20747 #define NIL_SUPER (struct super_block *) 0
- 20748 #define IMAP 0 /* operating on the inode bit map */
- 20749 #define ZMAP 1 /* operating on the zone bit map */
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/table.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 20800 /* This file contains the table used to map system call numbers onto the
- 20801 * routines that perform them.
- 20802 */
- 20803
- 20804 #define _TABLE
- 20805
- 20806 #include "fs.h"
- 20807 #include <minix/callnr.h>
- 20808 #include <minix/com.h>
- 20809 #include "buf.h"
- 20810 #include "dev.h"
- 20811 #include "file.h"
- 20812 #include "fproc.h"
- 20813 #include "inode.h"
- 20814 #include "lock.h"
- 20815 #include "super.h"
- 20816
- 20817 PUBLIC _PROTOTYPE (int (*call_vector[NCALLS]), (void) ) = {
- 20818 no_sys, /* 0 = unused */
- 20819 do_exit, /* 1 = exit */
- 20820 do_fork, /* 2 = fork */
- 20821 do_read, /* 3 = read */
- 20822 do_write, /* 4 = write */
- 20823 do_open, /* 5 = open */
- 20824 do_close, /* 6 = close */
- 20825 no_sys, /* 7 = wait */
- 20826 do_creat, /* 8 = creat */
- 20827 do_link, /* 9 = link */
- 20828 do_unlink, /* 10 = unlink */
- 20829 no_sys, /* 11 = waitpid */
- 20830 do_chdir, /* 12 = chdir */
- 20831 do_time, /* 13 = time */
- 20832 do_mknod, /* 14 = mknod */
- 20833 do_chmod, /* 15 = chmod */
- 20834 do_chown, /* 16 = chown */
- 20835 no_sys, /* 17 = break */
- 20836 do_stat, /* 18 = stat */
- 20837 do_lseek, /* 19 = lseek */
- 20838 no_sys, /* 20 = getpid */
- 20839 do_mount, /* 21 = mount */
- 20840 do_umount, /* 22 = umount */
- 20841 do_set, /* 23 = setuid */
- 20842 no_sys, /* 24 = getuid */
- 20843 do_stime, /* 25 = stime */
- 20844 no_sys, /* 26 = ptrace */
- 20845 no_sys, /* 27 = alarm */
- 20846 do_fstat, /* 28 = fstat */
- 20847 no_sys, /* 29 = pause */
- 20848 do_utime, /* 30 = utime */
- 20849 no_sys, /* 31 = (stty) */
- 20850 no_sys, /* 32 = (gtty) */
- 20851 do_access, /* 33 = access */
- 20852 no_sys, /* 34 = (nice) */
- 20853 no_sys, /* 35 = (ftime) */
- 20854 do_sync, /* 36 = sync */
- 20855 no_sys, /* 37 = kill */
- 20856 do_rename, /* 38 = rename */
- 20857 do_mkdir, /* 39 = mkdir */
- 20858 do_unlink, /* 40 = rmdir */
- 20859 do_dup, /* 41 = dup */
- 20860 do_pipe, /* 42 = pipe */
- 20861 do_tims, /* 43 = times */
- 20862 no_sys, /* 44 = (prof) */
- 20863 no_sys, /* 45 = unused */
- 20864 do_set, /* 46 = setgid */
- 20865 no_sys, /* 47 = getgid */
- 20866 no_sys, /* 48 = (signal)*/
- 20867 no_sys, /* 49 = unused */
- 20868 no_sys, /* 50 = unused */
- 20869 no_sys, /* 51 = (acct) */
- 20870 no_sys, /* 52 = (phys) */
- 20871 no_sys, /* 53 = (lock) */
- 20872 do_ioctl, /* 54 = ioctl */
- 20873 do_fcntl, /* 55 = fcntl */
- 20874 no_sys, /* 56 = (mpx) */
- 20875 no_sys, /* 57 = unused */
- 20876 no_sys, /* 58 = unused */
- 20877 do_exec, /* 59 = execve */
- 20878 do_umask, /* 60 = umask */
- 20879 do_chroot, /* 61 = chroot */
- 20880 do_setsid, /* 62 = setsid */
- 20881 no_sys, /* 63 = getpgrp */
- 20882
- 20883 no_sys, /* 64 = KSIG: signals originating in the kernel */
- 20884 do_unpause, /* 65 = UNPAUSE */
- 20885 no_sys, /* 66 = unused */
- 20886 do_revive, /* 67 = REVIVE */
- 20887 no_sys, /* 68 = TASK_REPLY */
- 20888 no_sys, /* 69 = unused */
- 20889 no_sys, /* 70 = unused */
- 20890 no_sys, /* 71 = SIGACTION */
- 20891 no_sys, /* 72 = SIGSUSPEND */
- 20892 no_sys, /* 73 = SIGPENDING */
- 20893 no_sys, /* 74 = SIGPROCMASK */
- 20894 no_sys, /* 75 = SIGRETURN */
- 20895 no_sys, /* 76 = REBOOT */
- 20896 };
- 20897
- 20898
- 20899 /* Some devices may or may not be there in the next table. */
- 20900 #define DT(enable, open, rw, close, task)
- 20901 { (enable ? (open) : no_dev), (enable ? (rw) : no_dev),
- 20902 (enable ? (close) : no_dev), (enable ? (task) : 0) },
- 20903
- 20904 /* The order of the entries here determines the mapping between major device
- 20905 * numbers and tasks. The first entry (major device 0) is not used. The
- 20906 * next entry is major device 1, etc. Character and block devices can be
- 20907 * intermixed at random. If this ordering is changed, the devices in
- 20908 * <include/minix/boot.h> must be changed to correspond to the new values.
- 20909 * Note that the major device numbers used in /dev are NOT the same as the
- 20910 * task numbers used inside the kernel (as defined in <include/minix/com.h>).
- 20911 * Also note that if /dev/mem is changed from 1, NULL_MAJOR must be changed
- 20912 * in <include/minix/com.h>.
- 20913 */
- 20914 PUBLIC struct dmap dmap[] = {
- 20915 /* ? Open Read/Write Close Task # Device File
- 20916 - ---- ---------- ----- ------- ------ ---- */
- 20917 DT(1, no_dev, no_dev, no_dev, 0) /* 0 = not used */
- 20918 DT(1, dev_opcl, call_task, dev_opcl, MEM) /* 1 = /dev/mem */
- 20919 DT(1, dev_opcl, call_task, dev_opcl, FLOPPY) /* 2 = /dev/fd0 */
- 20920 DT(ENABLE_WINI,
- 20921 dev_opcl, call_task, dev_opcl, WINCHESTER) /* 3 = /dev/hd0 */
- 20922 DT(1, tty_open, call_task, dev_opcl, TTY) /* 4 = /dev/tty00 */
- 20923 DT(1, ctty_open, call_ctty, ctty_close, TTY) /* 5 = /dev/tty */
- 20924 DT(1, dev_opcl, call_task, dev_opcl, PRINTER) /* 6 = /dev/lp */
- 20925
- 20926 #if (MACHINE == IBM_PC)
- 20927 DT(ENABLE_NETWORKING,
- 20928 net_open, call_task, dev_opcl, INET_PROC_NR)/* 7 = /dev/ip */
- 20929 DT(ENABLE_CDROM,
- 20930 dev_opcl, call_task, dev_opcl, CDROM) /* 8 = /dev/cd0 */
- 20931 DT(0, 0, 0, 0, 0) /* 9 = not used */
- 20932 DT(ENABLE_SCSI,
- 20933 dev_opcl, call_task, dev_opcl, SCSI) /*10 = /dev/sd0 */
- 20934 DT(0, 0, 0, 0, 0) /*11 = not used */
- 20935 DT(0, 0, 0, 0, 0) /*12 = not used */
- 20936 DT(ENABLE_AUDIO,
- 20937 dev_opcl, call_task, dev_opcl, AUDIO) /*13 = /dev/audio */
- 20938 DT(ENABLE_AUDIO,
- 20939 dev_opcl, call_task, dev_opcl, MIXER) /*14 = /dev/mixer */
- 20940 #endif /* IBM_PC */
- 20941
- 20942 #if (MACHINE == ATARI)
- 20943 DT(ENABLE_SCSI,
- 20944 dev_opcl, call_task, dev_opcl, SCSI) /* 7 = /dev/hdscsi0 */
- 20945 #endif
- 20946 };
- 20947
- 20948 PUBLIC int max_major = sizeof(dmap)/sizeof(struct dmap);
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/fs/cache.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 21000 /* The file system maintains a buffer cache to reduce the number of disk
- 21001 * accesses needed. Whenever a read or write to the disk is done, a check is
- 21002 * first made to see if the block is in the cache. This file manages the
- 21003 * cache.
- 21004 *
- 21005 * The entry points into this file are:
- 21006 * get_block: request to fetch a block for reading or writing from cache
- 21007 * put_block: return a block previously requested with get_block
- 21008 * alloc_zone: allocate a new zone (to increase the length of a file)
- 21009 * free_zone: release a zone (when a file is removed)
- 21010 * rw_block: read or write a block from the disk itself
- 21011 * invalidate: remove all the cache blocks on some device
- 21012 */
- 21013
- 21014 #include "fs.h"
- 21015 #include <minix/com.h>
- 21016 #include <minix/boot.h>
- 21017 #include "buf.h"
- 21018 #include "file.h"
- 21019 #include "fproc.h"
- 21020 #include "super.h"
- 21021
- 21022 FORWARD _PROTOTYPE( void rm_lru, (struct buf *bp) );
- 21023
- 21024 /*===========================================================================*
- 21025 * get_block *
- 21026 *===========================================================================*/
- 21027 PUBLIC struct buf *get_block(dev, block, only_search)
- 21028 register dev_t dev; /* on which device is the block? */
- 21029 register block_t block; /* which block is wanted? */
- 21030 int only_search; /* if NO_READ, don't read, else act normal */
- 21031 {
- 21032 /* Check to see if the requested block is in the block cache. If so, return
- 21033 * a pointer to it. If not, evict some other block and fetch it (unless
- 21034 * 'only_search' is 1). All the blocks in the cache that are not in use
- 21035 * are linked together in a chain, with 'front' pointing to the least recently
- 21036 * used block and 'rear' to the most recently used block. If 'only_search' is
- 21037 * 1, the block being requested will be overwritten in its entirety, so it is
- 21038 * only necessary to see if it is in the cache; if it is not, any free buffer
- 21039 * will do. It is not necessary to actually read the block in from disk.
- 21040 * If 'only_search' is PREFETCH, the block need not be read from the disk,
- 21041 * and the device is not to be marked on the block, so callers can tell if
- 21042 * the block returned is valid.
- 21043 * In addition to the LRU chain, there is also a hash chain to link together
- 21044 * blocks whose block numbers end with the same bit strings, for fast lookup.
- 21045 */
- 21046
- 21047 int b;
- 21048 register struct buf *bp, *prev_ptr;
- 21049
- 21050 /* Search the hash chain for (dev, block). Do_read() can use
- 21051 * get_block(NO_DEV ...) to get an unnamed block to fill with zeros when
- 21052 * someone wants to read from a hole in a file, in which case this search
- 21053 * is skipped
- 21054 */
- 21055 if (dev != NO_DEV) {
- 21056 b = (int) block & HASH_MASK;
- 21057 bp = buf_hash[b];
- 21058 while (bp != NIL_BUF) {
- 21059 if (bp->b_blocknr == block && bp->b_dev == dev) {
- 21060 /* Block needed has been found. */
- 21061 if (bp->b_count == 0) rm_lru(bp);
- 21062 bp->b_count++; /* record that block is in use */
- 21063 return(bp);
- 21064 } else {
- 21065 /* This block is not the one sought. */
- 21066 bp = bp->b_hash; /* move to next block on hash chain */
- 21067 }
- 21068 }
- 21069 }
- 21070
- 21071 /* Desired block is not on available chain. Take oldest block ('front'). */
- 21072 if ((bp = front) == NIL_BUF) panic("all buffers in use", NR_BUFS);
- 21073 rm_lru(bp);
- 21074
- 21075 /* Remove the block that was just taken from its hash chain. */
- 21076 b = (int) bp->b_blocknr & HASH_MASK;
- 21077 prev_ptr = buf_hash[b];
- 21078 if (prev_ptr == bp) {
- 21079 buf_hash[b] = bp->b_hash;
- 21080 } else {
- 21081 /* The block just taken is not on the front of its hash chain. */
- 21082 while (prev_ptr->b_hash != NIL_BUF)
- 21083 if (prev_ptr->b_hash == bp) {
- 21084 prev_ptr->b_hash = bp->b_hash; /* found it */
- 21085 break;
- 21086 } else {
- 21087 prev_ptr = prev_ptr->b_hash; /* keep looking */
- 21088 }
- 21089 }
- 21090
- 21091 /* If the block taken is dirty, make it clean by writing it to the disk.
- 21092 * Avoid hysteresis by flushing all other dirty blocks for the same device.
- 21093 */
- 21094 if (bp->b_dev != NO_DEV) {
- 21095 if (bp->b_dirt == DIRTY) flushall(bp->b_dev);
- 21096 }
- 21097
- 21098 /* Fill in block's parameters and add it to the hash chain where it goes. */
- 21099 bp->b_dev = dev; /* fill in device number */
- 21100 bp->b_blocknr = block; /* fill in block number */
- 21101 bp->b_count++; /* record that block is being used */
- 21102 b = (int) bp->b_blocknr & HASH_MASK;
- 21103 bp->b_hash = buf_hash[b];
- 21104 buf_hash[b] = bp; /* add to hash list */
- 21105
- 21106 /* Go get the requested block unless searching or prefetching. */
- 21107 if (dev != NO_DEV) {
- 21108 if (only_search == PREFETCH) bp->b_dev = NO_DEV;
- 21109 else
- 21110 if (only_search == NORMAL) rw_block(bp, READING);
- 21111 }
- 21112 return(bp); /* return the newly acquired block */
- 21113 }
-
-
- 21116 /*===========================================================================*
- 21117 * put_block *
- 21118 *===========================================================================*/
- 21119 PUBLIC void put_block(bp, block_type)
- 21120 register struct buf *bp; /* pointer to the buffer to be released */
- 21121 int block_type; /* INODE_BLOCK, DIRECTORY_BLOCK, or whatever */
- 21122 {
- 21123 /* Return a block to the list of available blocks. Depending on 'block_type'
- 21124 * it may be put on the front or rear of the LRU chain. Blocks that are
- 21125 * expected to be needed again shortly (e.g., partially full data blocks)
- 21126 * go on the rear; blocks that are unlikely to be needed again shortly
- 21127 * (e.g., full data blocks) go on the front. Blocks whose loss can hurt
- 21128 * the integrity of the file system (e.g., inode blocks) are written to
- 21129 * disk immediately if they are dirty.
- 21130 */
- 21131
- 21132 if (bp == NIL_BUF) return; /* it is easier to check here than in caller */
- 21133
- 21134 bp->b_count--; /* there is one use fewer now */
- 21135 if (bp->b_count != 0) return; /* block is still in use */
- 21136
- 21137 bufs_in_use--; /* one fewer block buffers in use */
- 21138
- 21139 /* Put this block back on the LRU chain. If the ONE_SHOT bit is set in
- 21140 * 'block_type', the block is not likely to be needed again shortly, so put
- 21141 * it on the front of the LRU chain where it will be the first one to be
- 21142 * taken when a free buffer is needed later.
- 21143 */
- 21144 if (block_type & ONE_SHOT) {
- 21145 /* Block probably won't be needed quickly. Put it on front of chain.
- 21146 * It will be the next block to be evicted from the cache.
- 21147 */
- 21148 bp->b_prev = NIL_BUF;
- 21149 bp->b_next = front;
- 21150 if (front == NIL_BUF)
- 21151 rear = bp; /* LRU chain was empty */
- 21152 else
- 21153 front->b_prev = bp;
- 21154 front = bp;
- 21155 } else {
- 21156 /* Block probably will be needed quickly. Put it on rear of chain.
- 21157 * It will not be evicted from the cache for a long time.
- 21158 */
- 21159 bp->b_prev = rear;
- 21160 bp->b_next = NIL_BUF;
- 21161 if (rear == NIL_BUF)
- 21162 front = bp;
- 21163 else
- 21164 rear->b_next = bp;
- 21165 rear = bp;
- 21166 }
- 21167
- 21168 /* Some blocks are so important (e.g., inodes, indirect blocks) that they
- 21169 * should be written to the disk immediately to avoid messing up the file
- 21170 * system in the event of a crash.
- 21171 */
- 21172 if ((block_type & WRITE_IMMED) && bp->b_dirt==DIRTY && bp->b_dev != NO_DEV)
- 21173 rw_block(bp, WRITING);
- 21174 }
-
-
- 21177 /*===========================================================================*
- 21178 * alloc_zone *
- 21179 *===========================================================================*/
- 21180 PUBLIC zone_t alloc_zone(dev, z)
- 21181 dev_t dev; /* device where zone wanted */
- 21182 zone_t z; /* try to allocate new zone near this one */
- 21183 {
- 21184 /* Allocate a new zone on the indicated device and return its number. */
- 21185
- 21186 int major, minor;
- 21187 bit_t b, bit;
- 21188 struct super_block *sp;
- 21189
- 21190 /* Note that the routine alloc_bit() returns 1 for the lowest possible
- 21191 * zone, which corresponds to sp->s_firstdatazone. To convert a value
- 21192 * between the bit number, 'b', used by alloc_bit() and the zone number, 'z',
- 21193 * stored in the inode, use the formula:
- 21194 * z = b + sp->s_firstdatazone - 1
- 21195 * Alloc_bit() never returns 0, since this is used for NO_BIT (failure).
- 21196 */
- 21197 sp = get_super(dev); /* find the super_block for this device */
- 21198
- 21199 /* If z is 0, skip initial part of the map known to be fully in use. */
- 21200 if (z == sp->s_firstdatazone) {
- 21201 bit = sp->s_zsearch;
- 21202 } else {
- 21203 bit = (bit_t) z - (sp->s_firstdatazone - 1);
- 21204 }
- 21205 b = alloc_bit(sp, ZMAP, bit);
- 21206 if (b == NO_BIT) {
- 21207 err_code = ENOSPC;
- 21208 major = (int) (sp->s_dev >> MAJOR) & BYTE;
- 21209 minor = (int) (sp->s_dev >> MINOR) & BYTE;
- 21210 printf("No space on %sdevice %d/%dn",
- 21211 sp->s_dev == ROOT_DEV ? "root " : "", major, minor);
- 21212 return(NO_ZONE);
- 21213 }
- 21214 if (z == sp->s_firstdatazone) sp->s_zsearch = b; /* for next time */