BOOK.T
上传用户:jnzhq888
上传日期:2007-01-18
资源大小:51694k
文件大小:987k
源码类别:

操作系统开发

开发平台:

WINDOWS

  1. 17234                 rmp->mp_effuid = s_buf.st_uid;
  2. 17235                 tell_fs(SETUID,who, (int)rmp->mp_realuid, (int)rmp->mp_effuid);
  3. 17236         }
  4. 17237         if (s_buf.st_mode & I_SET_GID_BIT) {
  5. 17238                 rmp->mp_effgid = s_buf.st_gid;
  6. 17239                 tell_fs(SETGID,who, (int)rmp->mp_realgid, (int)rmp->mp_effgid);
  7. 17240         }
  8. 17241   }
  9. 17242
  10. 17243   /* Save offset to initial argc (for ps) */
  11. 17244   rmp->mp_procargs = vsp;
  12. 17245
  13. 17246   /* Fix 'mproc' fields, tell kernel that exec is done,  reset caught sigs. */
  14. 17247   for (sn = 1; sn <= _NSIG; sn++) {
  15. 17248         if (sigismember(&rmp->mp_catch, sn)) {
  16. 17249                 sigdelset(&rmp->mp_catch, sn);
  17. 17250                 rmp->mp_sigact[sn].sa_handler = SIG_DFL;
  18. 17251                 sigemptyset(&rmp->mp_sigact[sn].sa_mask);
  19. 17252         }
  20. 17253   }
  21. 17254
  22. 17255   rmp->mp_flags &= ~SEPARATE;   /* turn off SEPARATE bit */
  23. 17256   rmp->mp_flags |= ft;          /* turn it on for separate I & D files */
  24. 17257   new_sp = (char *) vsp;
  25. 17258
  26. 17259   tell_fs(EXEC, who, 0, 0);     /* allow FS to handle FD_CLOEXEC files */
  27. .Op 239 src/mm/exec.c
  28. 17260
  29. 17261   /* System will save command line for debugging, ps(1) output, etc. */
  30. 17262   basename = strrchr(name_buf, '/');
  31. 17263   if (basename == NULL) basename = name_buf; else basename++;
  32. 17264   sys_exec(who, new_sp, rmp->mp_flags & TRACED, basename, pc);
  33. 17265   return(OK);
  34. 17266 }
  35. 17269 /*===========================================================================*
  36. 17270  *                              read_header                                  *
  37. 17271  *===========================================================================*/
  38. 17272 PRIVATE int read_header(fd, ft, text_bytes, data_bytes, bss_bytes, 
  39. 17273                                                 tot_bytes, sym_bytes, sc, pc)
  40. 17274 int fd;                         /* file descriptor for reading exec file */
  41. 17275 int *ft;                        /* place to return ft number */
  42. 17276 vir_bytes *text_bytes;          /* place to return text size */
  43. 17277 vir_bytes *data_bytes;          /* place to return initialized data size */
  44. 17278 vir_bytes *bss_bytes;           /* place to return bss size */
  45. 17279 phys_bytes *tot_bytes;          /* place to return total size */
  46. 17280 long *sym_bytes;                /* place to return symbol table size */
  47. 17281 vir_clicks sc;                  /* stack size in clicks */
  48. 17282 vir_bytes *pc;                  /* program entry point (initial PC) */
  49. 17283 {
  50. 17284 /* Read the header and extract the text, data, bss and total sizes from it. */
  51. 17285
  52. 17286   int m, ct;
  53. 17287   vir_clicks tc, dc, s_vir, dvir;
  54. 17288   phys_clicks totc;
  55. 17289   struct exec hdr;              /* a.out header is read in here */
  56. 17290
  57. 17291   /* Read the header and check the magic number.  The standard MINIX header 
  58. 17292    * is defined in <a.out.h>.  It consists of 8 chars followed by 6 longs.
  59. 17293    * Then come 4 more longs that are not used here.
  60. 17294    *    Byte 0: magic number 0x01
  61. 17295    *    Byte 1: magic number 0x03
  62. 17296    *    Byte 2: normal = 0x10 (not checked, 0 is OK), separate I/D = 0x20
  63. 17297    *    Byte 3: CPU type, Intel 16 bit = 0x04, Intel 32 bit = 0x10, 
  64. 17298    *            Motorola = 0x0B, Sun SPARC = 0x17
  65. 17299    *    Byte 4: Header length = 0x20
  66. 17300    *    Bytes 5-7 are not used.
  67. 17301    *
  68. 17302    *    Now come the 6 longs
  69. 17303    *    Bytes  8-11: size of text segments in bytes
  70. 17304    *    Bytes 12-15: size of initialized data segment in bytes
  71. 17305    *    Bytes 16-19: size of bss in bytes
  72. 17306    *    Bytes 20-23: program entry point
  73. 17307    *    Bytes 24-27: total memory allocated to program (text, data + stack)
  74. 17308    *    Bytes 28-31: size of symbol table in bytes
  75. 17309    * The longs are represented in a machine dependent order,
  76. 17310    * little-endian on the 8088, big-endian on the 68000.
  77. 17311    * The header is followed directly by the text and data segments, and the 
  78. 17312    * symbol table (if any). The sizes are given in the header. Only the 
  79. 17313    * text and data segments are copied into memory by exec. The header is 
  80. 17314    * used here only. The symbol table is for the benefit of a debugger and 
  81. 17315    * is ignored here.
  82. 17316    */
  83. 17317
  84. 17318   if (read(fd, (char *) &hdr, A_MINHDR) != A_MINHDR) return(ENOEXEC);
  85. 17319
  86. .Ep 240 src/mm/exec.c
  87. 17320   /* Check magic number, cpu type, and flags. */
  88. 17321   if (BADMAG(hdr)) return(ENOEXEC);
  89. 17322 #if (CHIP == INTEL && _WORD_SIZE == 2)
  90. 17323   if (hdr.a_cpu != A_I8086) return(ENOEXEC);
  91. 17324 #endif
  92. 17325 #if (CHIP == INTEL && _WORD_SIZE == 4)
  93. 17326   if (hdr.a_cpu != A_I80386) return(ENOEXEC);
  94. 17327 #endif
  95. 17328   if ((hdr.a_flags & ~(A_NSYM | A_EXEC | A_SEP)) != 0) return(ENOEXEC);
  96. 17329
  97. 17330   *ft = ( (hdr.a_flags & A_SEP) ? SEPARATE : 0);    /* separate I & D or not */
  98. 17331
  99. 17332   /* Get text and data sizes. */
  100. 17333   *text_bytes = (vir_bytes) hdr.a_text; /* text size in bytes */
  101. 17334   *data_bytes = (vir_bytes) hdr.a_data; /* data size in bytes */
  102. 17335   *bss_bytes  = (vir_bytes) hdr.a_bss;  /* bss size in bytes */
  103. 17336   *tot_bytes  = hdr.a_total;            /* total bytes to allocate for prog */
  104. 17337   *sym_bytes  = hdr.a_syms;             /* symbol table size in bytes */
  105. 17338   if (*tot_bytes == 0) return(ENOEXEC);
  106. 17339
  107. 17340   if (*ft != SEPARATE) {
  108. 17341
  109. 17342         /* If I & D space is not separated, it is all considered data. Text=0*/
  110. 17343         *data_bytes += *text_bytes;
  111. 17344         *text_bytes = 0;
  112. 17345
  113. 17346   }
  114. 17347   *pc = hdr.a_entry;    /* initial address to start execution */
  115. 17348
  116. 17349   /* Check to see if segment sizes are feasible. */
  117. 17350   tc = ((unsigned long) *text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
  118. 17351   dc = (*data_bytes + *bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
  119. 17352   totc = (*tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
  120. 17353   if (dc >= totc) return(ENOEXEC);      /* stack must be at least 1 click */
  121. 17354   dvir = (*ft == SEPARATE ? 0 : tc);
  122. 17355   s_vir = dvir + (totc - sc);
  123. 17356   m = size_ok(*ft, tc, dc, sc, dvir, s_vir);
  124. 17357   ct = hdr.a_hdrlen & BYTE;             /* header length */
  125. 17358   if (ct > A_MINHDR) lseek(fd, (off_t) ct, SEEK_SET); /* skip unused hdr */
  126. 17359   return(m);
  127. 17360 }
  128. 17363 /*===========================================================================*
  129. 17364  *                              new_mem                                      *
  130. 17365  *===========================================================================*/
  131. 17366 PRIVATE int new_mem(sh_mp, text_bytes, data_bytes,bss_bytes,stk_bytes,tot_bytes)
  132. 17367 struct mproc *sh_mp;            /* text can be shared with this process */
  133. 17368 vir_bytes text_bytes;           /* text segment size in bytes */
  134. 17369 vir_bytes data_bytes;           /* size of initialized data in bytes */
  135. 17370 vir_bytes bss_bytes;            /* size of bss in bytes */
  136. 17371 vir_bytes stk_bytes;            /* size of initial stack segment in bytes */
  137. 17372 phys_bytes tot_bytes;           /* total memory to allocate, including gap */
  138. 17373 {
  139. 17374 /* Allocate new memory and release the old memory.  Change the map and report
  140. 17375  * the new map to the kernel.  Zero the new core image's bss, gap and stack.
  141. 17376  */
  142. 17377
  143. 17378   register struct mproc *rmp;
  144. 17379   vir_clicks text_clicks, data_clicks, gap_clicks, stack_clicks, tot_clicks;
  145. .Op 241 src/mm/exec.c
  146. 17380   phys_clicks new_base;
  147. 17381
  148. 17382   static char zero[1024];               /* used to zero bss */
  149. 17383   phys_bytes bytes, base, count, bss_offset;
  150. 17384
  151. 17385   /* No need to allocate text if it can be shared. */
  152. 17386   if (sh_mp != NULL) text_bytes = 0;
  153. 17387
  154. 17388   /* Acquire the new memory.  Each of the 4 parts: text, (data+bss), gap,
  155. 17389    * and stack occupies an integral number of clicks, starting at click
  156. 17390    * boundary.  The data and bss parts are run together with no space.
  157. 17391    */
  158. 17392
  159. 17393   text_clicks = ((unsigned long) text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
  160. 17394   data_clicks = (data_bytes + bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
  161. 17395   stack_clicks = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
  162. 17396   tot_clicks = (tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
  163. 17397   gap_clicks = tot_clicks - data_clicks - stack_clicks;
  164. 17398   if ( (int) gap_clicks < 0) return(ENOMEM);
  165. 17399
  166. 17400   /* Check to see if there is a hole big enough.  If so, we can risk first
  167. 17401    * releasing the old core image before allocating the new one, since we
  168. 17402    * know it will succeed.  If there is not enough, return failure.
  169. 17403    */
  170. 17404   if (text_clicks + tot_clicks > max_hole()) return(EAGAIN);
  171. 17405
  172. 17406   /* There is enough memory for the new core image.  Release the old one. */
  173. 17407   rmp = mp;
  174. 17408
  175. 17409   if (find_share(rmp, rmp->mp_ino, rmp->mp_dev, rmp->mp_ctime) == NULL) {
  176. 17410         /* No other process shares the text segment, so free it. */
  177. 17411         free_mem(rmp->mp_seg[T].mem_phys, rmp->mp_seg[T].mem_len);
  178. 17412   }
  179. 17413   /* Free the data and stack segments. */
  180. 17414   free_mem(rmp->mp_seg[D].mem_phys,
  181. 17415       rmp->mp_seg[S].mem_vir + rmp->mp_seg[S].mem_len - rmp->mp_seg[D].mem_vir);
  182. 17416
  183. 17417   /* We have now passed the point of no return.  The old core image has been
  184. 17418    * forever lost.  The call must go through now.  Set up and report new map.
  185. 17419    */
  186. 17420   new_base = alloc_mem(text_clicks + tot_clicks);       /* new core image */
  187. 17421   if (new_base == NO_MEM) panic("MM hole list is inconsistent", NO_NUM);
  188. 17422
  189. 17423   if (sh_mp != NULL) {
  190. 17424         /* Share the text segment. */
  191. 17425         rmp->mp_seg[T] = sh_mp->mp_seg[T];
  192. 17426   } else {
  193. 17427         rmp->mp_seg[T].mem_phys = new_base;
  194. 17428         rmp->mp_seg[T].mem_vir = 0;
  195. 17429         rmp->mp_seg[T].mem_len = text_clicks;
  196. 17430   }
  197. 17431   rmp->mp_seg[D].mem_phys = new_base + text_clicks;
  198. 17432   rmp->mp_seg[D].mem_vir = 0;
  199. 17433   rmp->mp_seg[D].mem_len = data_clicks;
  200. 17434   rmp->mp_seg[S].mem_phys = rmp->mp_seg[D].mem_phys + data_clicks + gap_clicks;
  201. 17435   rmp->mp_seg[S].mem_vir = rmp->mp_seg[D].mem_vir + data_clicks + gap_clicks;
  202. 17436   rmp->mp_seg[S].mem_len = stack_clicks;
  203. 17437
  204. 17438
  205. 17439   sys_newmap(who, rmp->mp_seg);   /* report new map to the kernel */
  206. .Ep 242 src/mm/exec.c
  207. 17440
  208. 17441   /* Zero the bss, gap, and stack segment. */
  209. 17442   bytes = (phys_bytes)(data_clicks + gap_clicks + stack_clicks) << CLICK_SHIFT;
  210. 17443   base = (phys_bytes) rmp->mp_seg[D].mem_phys << CLICK_SHIFT;
  211. 17444   bss_offset = (data_bytes >> CLICK_SHIFT) << CLICK_SHIFT;
  212. 17445   base += bss_offset;
  213. 17446   bytes -= bss_offset;
  214. 17447
  215. 17448   while (bytes > 0) {
  216. 17449         count = MIN(bytes, (phys_bytes) sizeof(zero));
  217. 17450         if (sys_copy(MM_PROC_NR, D, (phys_bytes) zero,
  218. 17451                                                 ABS, 0, base, count) != OK) {
  219. 17452                 panic("new_mem can't zero", NO_NUM);
  220. 17453         }
  221. 17454         base += count;
  222. 17455         bytes -= count;
  223. 17456   }
  224. 17457
  225. 17458   return(OK);
  226. 17459 }
  227. 17462 /*===========================================================================*
  228. 17463  *                              patch_ptr                                    *
  229. 17464  *===========================================================================*/
  230. 17465 PRIVATE void patch_ptr(stack, base)
  231. 17466 char stack[ARG_MAX];    /* pointer to stack image within MM */
  232. 17467 vir_bytes base;                 /* virtual address of stack base inside user */
  233. 17468 {
  234. 17469 /* When doing an exec(name, argv, envp) call, the user builds up a stack
  235. 17470  * image with arg and env pointers relative to the start of the stack.  Now
  236. 17471  * these pointers must be relocated, since the stack is not positioned at
  237. 17472  * address 0 in the user's address space.
  238. 17473  */
  239. 17474
  240. 17475   char **ap, flag;
  241. 17476   vir_bytes v;
  242. 17477
  243. 17478   flag = 0;                     /* counts number of 0-pointers seen */
  244. 17479   ap = (char **) stack;         /* points initially to 'nargs' */
  245. 17480   ap++;                         /* now points to argv[0] */
  246. 17481   while (flag < 2) {
  247. 17482         if (ap >= (char **) &stack[ARG_MAX]) return;    /* too bad */
  248. 17483         if (*ap != NIL_PTR) {
  249. 17484                 v = (vir_bytes) *ap;    /* v is relative pointer */
  250. 17485                 v += base;              /* relocate it */
  251. 17486                 *ap = (char *) v;       /* put it back */
  252. 17487         } else {
  253. 17488                 flag++;
  254. 17489         }
  255. 17490         ap++;
  256. 17491   }
  257. 17492 }
  258. 17495 /*===========================================================================*
  259. 17496  *                              load_seg                                     *
  260. 17497  *===========================================================================*/
  261. 17498 PRIVATE void load_seg(fd, seg, seg_bytes)
  262. 17499 int fd;                         /* file descriptor to read from */
  263. .Op 243 src/mm/exec.c
  264. 17500 int seg;                        /* T or D */
  265. 17501 vir_bytes seg_bytes;            /* how big is the segment */
  266. 17502 {
  267. 17503 /* Read in text or data from the exec file and copy to the new core image.
  268. 17504  * This procedure is a little bit tricky.  The logical way to load a segment
  269. 17505  * would be to read it block by block and copy each block to the user space
  270. 17506  * one at a time.  This is too slow, so we do something dirty here, namely
  271. 17507  * send the user space and virtual address to the file system in the upper
  272. 17508  * 10 bits of the file descriptor, and pass it the user virtual address
  273. 17509  * instead of a MM address.  The file system extracts these parameters when 
  274. 17510  * gets a read call from the memory manager, which is the only process that
  275. 17511  * is permitted to use this trick.  The file system then copies the whole 
  276. 17512  * segment directly to user space, bypassing MM completely.
  277. 17513  */
  278. 17514
  279. 17515   int new_fd, bytes;
  280. 17516   char *ubuf_ptr;
  281. 17517
  282. 17518   new_fd = (who << 8) | (seg << 6) | fd;
  283. 17519   ubuf_ptr = (char *) ((vir_bytes)mp->mp_seg[seg].mem_vir << CLICK_SHIFT);
  284. 17520   while (seg_bytes != 0) {
  285. 17521         bytes = (INT_MAX / BLOCK_SIZE) * BLOCK_SIZE;
  286. 17522         if (seg_bytes < bytes)
  287. 17523                 bytes = (int)seg_bytes;
  288. 17524         if (read(new_fd, ubuf_ptr, bytes) != bytes)
  289. 17525                 break;          /* error */
  290. 17526         ubuf_ptr += bytes;
  291. 17527         seg_bytes -= bytes;
  292. 17528   }
  293. 17529 }
  294. 17532 /*===========================================================================*
  295. 17533  *                              find_share                                   *
  296. 17534  *===========================================================================*/
  297. 17535 PUBLIC struct mproc *find_share(mp_ign, ino, dev, ctime)
  298. 17536 struct mproc *mp_ign;           /* process that should not be looked at */
  299. 17537 ino_t ino;                      /* parameters that uniquely identify a file */
  300. 17538 dev_t dev;
  301. 17539 time_t ctime;
  302. 17540 {
  303. 17541 /* Look for a process that is the file <ino, dev, ctime> in execution.  Don't
  304. 17542  * accidentally "find" mp_ign, because it is the process on whose behalf this
  305. 17543  * call is made.
  306. 17544  */
  307. 17545   struct mproc *sh_mp;
  308. 17546
  309. 17547   for (sh_mp = &mproc[INIT_PROC_NR]; sh_mp < &mproc[NR_PROCS]; sh_mp++) {
  310. 17548         if ((sh_mp->mp_flags & (IN_USE | HANGING | SEPARATE))
  311. 17549                                         != (IN_USE | SEPARATE)) continue;
  312. 17550         if (sh_mp == mp_ign) continue;
  313. 17551         if (sh_mp->mp_ino != ino) continue;
  314. 17552         if (sh_mp->mp_dev != dev) continue;
  315. 17553         if (sh_mp->mp_ctime != ctime) continue;
  316. 17554         return sh_mp;
  317. 17555   }
  318. 17556   return(NULL);
  319. 17557 }
  320. .Ep 244 src/mm/break.c
  321. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  322. src/mm/break.c    
  323. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  324. 17600 /* The MINIX model of memory allocation reserves a fixed amount of memory for
  325. 17601  * the combined text, data, and stack segments.  The amount used for a child
  326. 17602  * process created by FORK is the same as the parent had.  If the child does
  327. 17603  * an EXEC later, the new size is taken from the header of the file EXEC'ed.
  328. 17604  *
  329. 17605  * The layout in memory consists of the text segment, followed by the data
  330. 17606  * segment, followed by a gap (unused memory), followed by the stack segment.
  331. 17607  * The data segment grows upward and the stack grows downward, so each can
  332. 17608  * take memory from the gap.  If they meet, the process must be killed.  The
  333. 17609  * procedures in this file deal with the growth of the data and stack segments.
  334. 17610  *
  335. 17611  * The entry points into this file are:
  336. 17612  *   do_brk:      BRK/SBRK system calls to grow or shrink the data segment
  337. 17613  *   adjust:      see if a proposed segment adjustment is allowed
  338. 17614  *   size_ok:     see if the segment sizes are feasible
  339. 17615  */
  340. 17616
  341. 17617 #include "mm.h"
  342. 17618 #include <signal.h>
  343. 17619 #include "mproc.h"
  344. 17620 #include "param.h"
  345. 17621
  346. 17622 #define DATA_CHANGED       1    /* flag value when data segment size changed */
  347. 17623 #define STACK_CHANGED      2    /* flag value when stack size changed */
  348. 17624
  349. 17625 /*===========================================================================*
  350. 17626  *                              do_brk                                       *
  351. 17627  *===========================================================================*/
  352. 17628 PUBLIC int do_brk()
  353. 17629 {
  354. 17630 /* Perform the brk(addr) system call.
  355. 17631  *
  356. 17632  * The call is complicated by the fact that on some machines (e.g., 8088),
  357. 17633  * the stack pointer can grow beyond the base of the stack segment without
  358. 17634  * anybody noticing it.
  359. 17635  * The parameter, 'addr' is the new virtual address in D space.
  360. 17636  */
  361. 17637
  362. 17638   register struct mproc *rmp;
  363. 17639   int r;
  364. 17640   vir_bytes v, new_sp;
  365. 17641   vir_clicks new_clicks;
  366. 17642
  367. 17643   rmp = mp;
  368. 17644   v = (vir_bytes) addr;
  369. 17645   new_clicks = (vir_clicks) ( ((long) v + CLICK_SIZE - 1) >> CLICK_SHIFT);
  370. 17646   if (new_clicks < rmp->mp_seg[D].mem_vir) {
  371. 17647         res_ptr = (char *) -1;
  372. 17648         return(ENOMEM);
  373. 17649   }
  374. 17650   new_clicks -= rmp->mp_seg[D].mem_vir;
  375. 17651   sys_getsp(who, &new_sp);      /* ask kernel for current sp value */
  376. 17652   r = adjust(rmp, new_clicks, new_sp);
  377. 17653   res_ptr = (r == OK ? addr : (char *) -1);
  378. 17654   return(r);                    /* return new address or -1 */
  379. .Op 245 src/mm/break.c
  380. 17655 }
  381. 17658 /*===========================================================================*
  382. 17659  *                              adjust                                       *
  383. 17660  *===========================================================================*/
  384. 17661 PUBLIC int adjust(rmp, data_clicks, sp)
  385. 17662 register struct mproc *rmp;     /* whose memory is being adjusted? */
  386. 17663 vir_clicks data_clicks;         /* how big is data segment to become? */
  387. 17664 vir_bytes sp;                   /* new value of sp */
  388. 17665 {
  389. 17666 /* See if data and stack segments can coexist, adjusting them if need be.
  390. 17667  * Memory is never allocated or freed.  Instead it is added or removed from the
  391. 17668  * gap between data segment and stack segment.  If the gap size becomes
  392. 17669  * negative, the adjustment of data or stack fails and ENOMEM is returned.
  393. 17670  */
  394. 17671
  395. 17672   register struct mem_map *mem_sp, *mem_dp;
  396. 17673   vir_clicks sp_click, gap_base, lower, old_clicks;
  397. 17674   int changed, r, ft;
  398. 17675   long base_of_stack, delta;    /* longs avoid certain problems */
  399. 17676
  400. 17677   mem_dp = &rmp->mp_seg[D];     /* pointer to data segment map */
  401. 17678   mem_sp = &rmp->mp_seg[S];     /* pointer to stack segment map */
  402. 17679   changed = 0;                  /* set when either segment changed */
  403. 17680
  404. 17681   if (mem_sp->mem_len == 0) return(OK); /* don't bother init */
  405. 17682
  406. 17683   /* See if stack size has gone negative (i.e., sp too close to 0xFFFF...) */
  407. 17684   base_of_stack = (long) mem_sp->mem_vir + (long) mem_sp->mem_len;
  408. 17685   sp_click = sp >> CLICK_SHIFT; /* click containing sp */
  409. 17686   if (sp_click >= base_of_stack) return(ENOMEM);        /* sp too high */
  410. 17687
  411. 17688   /* Compute size of gap between stack and data segments. */
  412. 17689   delta = (long) mem_sp->mem_vir - (long) sp_click;
  413. 17690   lower = (delta > 0 ? sp_click : mem_sp->mem_vir);
  414. 17691
  415. 17692   /* Add a safety margin for future stack growth. Impossible to do right. */
  416. 17693 #define SAFETY_BYTES  (384 * sizeof(char *))
  417. 17694 #define SAFETY_CLICKS ((SAFETY_BYTES + CLICK_SIZE - 1) / CLICK_SIZE)
  418. 17695   gap_base = mem_dp->mem_vir + data_clicks + SAFETY_CLICKS;
  419. 17696   if (lower < gap_base) return(ENOMEM); /* data and stack collided */
  420. 17697
  421. 17698   /* Update data length (but not data orgin) on behalf of brk() system call. */
  422. 17699   old_clicks = mem_dp->mem_len;
  423. 17700   if (data_clicks != mem_dp->mem_len) {
  424. 17701         mem_dp->mem_len = data_clicks;
  425. 17702         changed |= DATA_CHANGED;
  426. 17703   }
  427. 17704
  428. 17705   /* Update stack length and origin due to change in stack pointer. */
  429. 17706   if (delta > 0) {
  430. 17707         mem_sp->mem_vir -= delta;
  431. 17708         mem_sp->mem_phys -= delta;
  432. 17709         mem_sp->mem_len += delta;
  433. 17710         changed |= STACK_CHANGED;
  434. 17711   }
  435. 17712
  436. 17713   /* Do the new data and stack segment sizes fit in the address space? */
  437. 17714   ft = (rmp->mp_flags & SEPARATE);
  438. .Ep 246 src/mm/break.c
  439. 17715   r = size_ok(ft, rmp->mp_seg[T].mem_len, rmp->mp_seg[D].mem_len, 
  440. 17716        rmp->mp_seg[S].mem_len, rmp->mp_seg[D].mem_vir, rmp->mp_seg[S].mem_vir);
  441. 17717   if (r == OK) {
  442. 17718         if (changed) sys_newmap((int)(rmp - mproc), rmp->mp_seg);
  443. 17719         return(OK);
  444. 17720   }
  445. 17721
  446. 17722   /* New sizes don't fit or require too many page/segment registers. Restore.*/
  447. 17723   if (changed & DATA_CHANGED) mem_dp->mem_len = old_clicks;
  448. 17724   if (changed & STACK_CHANGED) {
  449. 17725         mem_sp->mem_vir += delta;
  450. 17726         mem_sp->mem_phys += delta;
  451. 17727         mem_sp->mem_len -= delta;
  452. 17728   }
  453. 17729   return(ENOMEM);
  454. 17730 }
  455. 17733 /*===========================================================================*
  456. 17734  *                              size_ok                                      *
  457. 17735  *===========================================================================*/
  458. 17736 PUBLIC int size_ok(file_type, tc, dc, sc, dvir, s_vir)
  459. 17737 int file_type;                  /* SEPARATE or 0 */
  460. 17738 vir_clicks tc;                  /* text size in clicks */
  461. 17739 vir_clicks dc;                  /* data size in clicks */
  462. 17740 vir_clicks sc;                  /* stack size in clicks */
  463. 17741 vir_clicks dvir;                /* virtual address for start of data seg */
  464. 17742 vir_clicks s_vir;               /* virtual address for start of stack seg */
  465. 17743 {
  466. 17744 /* Check to see if the sizes are feasible and enough segmentation registers
  467. 17745  * exist.  On a machine with eight 8K pages, text, data, stack sizes of
  468. 17746  * (32K, 16K, 16K) will fit, but (33K, 17K, 13K) will not, even though the
  469. 17747  * former is bigger (64K) than the latter (63K).  Even on the 8088 this test
  470. 17748  * is needed, since the data and stack may not exceed 4096 clicks.
  471. 17749  */
  472. 17750
  473. 17751 #if (CHIP == INTEL && _WORD_SIZE == 2)
  474. 17752   int pt, pd, ps;               /* segment sizes in pages */
  475. 17753
  476. 17754   pt = ( (tc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
  477. 17755   pd = ( (dc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
  478. 17756   ps = ( (sc << CLICK_SHIFT) + PAGE_SIZE - 1)/PAGE_SIZE;
  479. 17757
  480. 17758   if (file_type == SEPARATE) {
  481. 17759         if (pt > MAX_PAGES || pd + ps > MAX_PAGES) return(ENOMEM);
  482. 17760   } else {
  483. 17761         if (pt + pd + ps > MAX_PAGES) return(ENOMEM);
  484. 17762   }
  485. 17763 #endif
  486. 17764
  487. 17765   if (dvir + dc > s_vir) return(ENOMEM);
  488. 17766
  489. 17767   return(OK);
  490. 17768 }
  491. .Op 247 src/mm/signal.c
  492. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  493. src/mm/signal.c    
  494. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  495. 17800 /* This file handles signals, which are asynchronous events and are generally
  496. 17801  * a messy and unpleasant business.  Signals can be generated by the KILL
  497. 17802  * system call, or from the keyboard (SIGINT) or from the clock (SIGALRM).
  498. 17803  * In all cases control eventually passes to check_sig() to see which processes
  499. 17804  * can be signaled.  The actual signaling is done by sig_proc().
  500. 17805  *
  501. 17806  * The entry points into this file are:
  502. 17807  *   do_sigaction:   perform the SIGACTION system call
  503. 17808  *   do_sigpending:  perform the SIGPENDING system call
  504. 17809  *   do_sigprocmask: perform the SIGPROCMASK system call
  505. 17810  *   do_sigreturn:   perform the SIGRETURN system call
  506. 17811  *   do_sigsuspend:  perform the SIGSUSPEND system call
  507. 17812  *   do_kill:   perform the KILL system call
  508. 17813  *   do_ksig:   accept a signal originating in the kernel (e.g., SIGINT)
  509. 17814  *   do_alarm:  perform the ALARM system call by calling set_alarm()
  510. 17815  *   set_alarm: tell the clock task to start or stop a timer
  511. 17816  *   do_pause:  perform the PAUSE system call
  512. 17817  *   do_reboot: kill all processes, then reboot system
  513. 17818  *   sig_proc:  interrupt or terminate a signaled process
  514. 17819  *   check_sig: check which processes to signal with sig_proc()
  515. 17820  */
  516. 17821
  517. 17822 #include "mm.h"
  518. 17823 #include <sys/stat.h>
  519. 17824 #include <minix/callnr.h>
  520. 17825 #include <minix/com.h>
  521. 17826 #include <signal.h>
  522. 17827 #include <sys/sigcontext.h>
  523. 17828 #include <string.h>
  524. 17829 #include "mproc.h"
  525. 17830 #include "param.h"
  526. 17831
  527. 17832 #define CORE_MODE       0777    /* mode to use on core image files */
  528. 17833 #define DUMPED          0200    /* bit set in status when core dumped */
  529. 17834 #define DUMP_SIZE       ((INT_MAX / BLOCK_SIZE) * BLOCK_SIZE)
  530. 17835                                 /* buffer size for core dumps */
  531. 17836
  532. 17837 FORWARD _PROTOTYPE( void check_pending, (void)                          );
  533. 17838 FORWARD _PROTOTYPE( void dump_core, (struct mproc *rmp)                 );
  534. 17839 FORWARD _PROTOTYPE( void unpause, (int pro)                             );
  535. 17840
  536. 17841
  537. 17842 /*===========================================================================*
  538. 17843  *                             do_sigaction                                  *
  539. 17844  *===========================================================================*/
  540. 17845 PUBLIC int do_sigaction()
  541. 17846 {
  542. 17847   int r;
  543. 17848   struct sigaction svec;
  544. 17849   struct sigaction *svp;
  545. 17850
  546. 17851   if (sig_nr == SIGKILL) return(OK);
  547. 17852   if (sig_nr < 1 || sig_nr > _NSIG) return (EINVAL);
  548. 17853   svp = &mp->mp_sigact[sig_nr];
  549. 17854   if ((struct sigaction *) sig_osa != (struct sigaction *) NULL) {
  550. .Ep 248 src/mm/signal.c
  551. 17855         r = sys_copy(MM_PROC_NR,D, (phys_bytes) svp,
  552. 17856                 who, D, (phys_bytes) sig_osa, (phys_bytes) sizeof(svec));
  553. 17857         if (r != OK) return(r);
  554. 17858   }
  555. 17859
  556. 17860   if ((struct sigaction *) sig_nsa == (struct sigaction *) NULL) return(OK);
  557. 17861
  558. 17862   /* Read in the sigaction structure. */
  559. 17863   r = sys_copy(who, D, (phys_bytes) sig_nsa,
  560. 17864                 MM_PROC_NR, D, (phys_bytes) &svec, (phys_bytes) sizeof(svec));
  561. 17865   if (r != OK) return(r);
  562. 17866
  563. 17867   if (svec.sa_handler == SIG_IGN) {
  564. 17868         sigaddset(&mp->mp_ignore, sig_nr);
  565. 17869         sigdelset(&mp->mp_sigpending, sig_nr);
  566. 17870         sigdelset(&mp->mp_catch, sig_nr);
  567. 17871   } else {
  568. 17872         sigdelset(&mp->mp_ignore, sig_nr);
  569. 17873         if (svec.sa_handler == SIG_DFL)
  570. 17874                 sigdelset(&mp->mp_catch, sig_nr);
  571. 17875         else
  572. 17876                 sigaddset(&mp->mp_catch, sig_nr);
  573. 17877   }
  574. 17878   mp->mp_sigact[sig_nr].sa_handler = svec.sa_handler;
  575. 17879   sigdelset(&svec.sa_mask, SIGKILL);
  576. 17880   mp->mp_sigact[sig_nr].sa_mask = svec.sa_mask;
  577. 17881   mp->mp_sigact[sig_nr].sa_flags = svec.sa_flags;
  578. 17882   mp->mp_sigreturn = (vir_bytes) sig_ret;
  579. 17883   return(OK);
  580. 17884 }
  581. 17886 /*===========================================================================*
  582. 17887  *                            do_sigpending                                  *
  583. 17888  *===========================================================================*/
  584. 17889 PUBLIC int do_sigpending()
  585. 17890 {
  586. 17891   ret_mask = (long) mp->mp_sigpending;
  587. 17892   return OK;
  588. 17893 }
  589. 17895 /*===========================================================================*
  590. 17896  *                            do_sigprocmask                                 *
  591. 17897  *===========================================================================*/
  592. 17898 PUBLIC int do_sigprocmask()
  593. 17899 {
  594. 17900 /* Note that the library interface passes the actual mask in sigmask_set,
  595. 17901  * not a pointer to the mask, in order to save a sys_copy.  Similarly,
  596. 17902  * the old mask is placed in the return message which the library
  597. 17903  * interface copies (if requested) to the user specified address.
  598. 17904  *
  599. 17905  * The library interface must set SIG_INQUIRE if the 'act' argument
  600. 17906  * is NULL.
  601. 17907  */
  602. 17908
  603. 17909   int i;
  604. 17910
  605. 17911   ret_mask = (long) mp->mp_sigmask;
  606. 17912
  607. 17913   switch (sig_how) {
  608. 17914       case SIG_BLOCK:
  609. .Op 249 src/mm/signal.c
  610. 17915         sigdelset((sigset_t *)&sig_set, SIGKILL);
  611. 17916         for (i = 1; i < _NSIG; i++) {
  612. 17917                 if (sigismember((sigset_t *)&sig_set, i))
  613. 17918                         sigaddset(&mp->mp_sigmask, i);
  614. 17919         }
  615. 17920         break;
  616. 17921
  617. 17922       case SIG_UNBLOCK:
  618. 17923         for (i = 1; i < _NSIG; i++) {
  619. 17924                 if (sigismember((sigset_t *)&sig_set, i))
  620. 17925                         sigdelset(&mp->mp_sigmask, i);
  621. 17926         }
  622. 17927         check_pending();
  623. 17928         break;
  624. 17929
  625. 17930       case SIG_SETMASK:
  626. 17931         sigdelset((sigset_t *)&sig_set, SIGKILL);
  627. 17932         mp->mp_sigmask = (sigset_t)sig_set;
  628. 17933         check_pending();
  629. 17934         break;
  630. 17935
  631. 17936       case SIG_INQUIRE:
  632. 17937         break;
  633. 17938
  634. 17939       default:
  635. 17940         return(EINVAL);
  636. 17941         break;
  637. 17942   }
  638. 17943   return OK;
  639. 17944 }
  640. 17946 /*===========================================================================*
  641. 17947  *                            do_sigsuspend                                  *
  642. 17948  *===========================================================================*/
  643. 17949 PUBLIC int do_sigsuspend()
  644. 17950 {
  645. 17951   mp->mp_sigmask2 = mp->mp_sigmask;     /* save the old mask */
  646. 17952   mp->mp_sigmask = (sigset_t) sig_set;
  647. 17953   sigdelset(&mp->mp_sigmask, SIGKILL);
  648. 17954   mp->mp_flags |= SIGSUSPENDED;
  649. 17955   dont_reply = TRUE;
  650. 17956   check_pending();
  651. 17957   return OK;
  652. 17958 }
  653. 17961 /*===========================================================================*
  654. 17962  *                               do_sigreturn                                *
  655. 17963  *===========================================================================*/
  656. 17964 PUBLIC int do_sigreturn()
  657. 17965 {
  658. 17966 /* A user signal handler is done.  Restore context and check for
  659. 17967  * pending unblocked signals.
  660. 17968  */
  661. 17969
  662. 17970   int r;
  663. 17971
  664. 17972   mp->mp_sigmask = (sigset_t) sig_set;
  665. 17973   sigdelset(&mp->mp_sigmask, SIGKILL);
  666. 17974
  667. .Ep 250 src/mm/signal.c
  668. 17975   r = sys_sigreturn(who, (vir_bytes)sig_context, sig_flags);
  669. 17976   check_pending();
  670. 17977   return(r);
  671. 17978 }
  672. 17980 /*===========================================================================*
  673. 17981  *                              do_kill                                      *
  674. 17982  *===========================================================================*/
  675. 17983 PUBLIC int do_kill()
  676. 17984 {
  677. 17985 /* Perform the kill(pid, signo) system call. */
  678. 17986
  679. 17987   return check_sig(pid, sig_nr);
  680. 17988 }
  681. 17991 /*===========================================================================*
  682. 17992  *                              do_ksig                                      *
  683. 17993  *===========================================================================*/
  684. 17994 PUBLIC int do_ksig()
  685. 17995 {
  686. 17996 /* Certain signals, such as segmentation violations and DEL, originate in the
  687. 17997  * kernel.  When the kernel detects such signals, it sets bits in a bit map.
  688. 17998  * As soon as MM is awaiting new work, the kernel sends MM a message containing
  689. 17999  * the process slot and bit map.  That message comes here.  The File System
  690. 18000  * also uses this mechanism to signal writing on broken pipes (SIGPIPE).
  691. 18001  */
  692. 18002
  693. 18003   register struct mproc *rmp;
  694. 18004   int i, proc_nr;
  695. 18005   pid_t proc_id, id;
  696. 18006   sigset_t sig_map;
  697. 18007
  698. 18008   /* Only kernel may make this call. */
  699. 18009   if (who != HARDWARE) return(EPERM);
  700. 18010   dont_reply = TRUE;            /* don't reply to the kernel */
  701. 18011   proc_nr = mm_in.SIG_PROC;
  702. 18012   rmp = &mproc[proc_nr];
  703. 18013   if ( (rmp->mp_flags & IN_USE) == 0 || (rmp->mp_flags & HANGING) ) return(OK);
  704. 18014   proc_id = rmp->mp_pid;
  705. 18015   sig_map = (sigset_t) mm_in.SIG_MAP;
  706. 18016   mp = &mproc[0];               /* pretend kernel signals are from MM */
  707. 18017   mp->mp_procgrp = rmp->mp_procgrp;     /* get process group right */
  708. 18018
  709. 18019   /* Check each bit in turn to see if a signal is to be sent.  Unlike
  710. 18020    * kill(), the kernel may collect several unrelated signals for a
  711. 18021    * process and pass them to MM in one blow.  Thus loop on the bit
  712. 18022    * map. For SIGINT and SIGQUIT, use proc_id 0 to indicate a broadcast
  713. 18023    * to the recipient's process group.  For SIGKILL, use proc_id -1 to
  714. 18024    * indicate a systemwide broadcast.
  715. 18025    */
  716. 18026   for (i = 1; i <= _NSIG; i++) {
  717. 18027         if (!sigismember(&sig_map, i)) continue;
  718. 18028         switch (i) {
  719. 18029             case SIGINT:
  720. 18030             case SIGQUIT:
  721. 18031                 id = 0; break;  /* broadcast to process group */
  722. 18032             case SIGKILL:
  723. 18033                 id = -1; break; /* broadcast to all except INIT */
  724. 18034             case SIGALRM:
  725. .Op 251 src/mm/signal.c
  726. 18035                 /* Disregard SIGALRM when the target process has not
  727. 18036                  * requested an alarm.  This only applies for a KERNEL
  728. 18037                  * generated signal.
  729. 18038                  */
  730. 18039                 if ((rmp->mp_flags & ALARM_ON) == 0) continue;
  731. 18040                 rmp->mp_flags &= ~ALARM_ON;
  732. 18041                 /* fall through */
  733. 18042             default:
  734. 18043                 id = proc_id;
  735. 18044                 break;
  736. 18045         }
  737. 18046         check_sig(id, i);
  738. 18047         sys_endsig(proc_nr);    /* tell kernel it's done */
  739. 18048   }
  740. 18049   return(OK);
  741. 18050 }
  742. 18053 /*===========================================================================*
  743. 18054  *                              do_alarm                                     *
  744. 18055  *===========================================================================*/
  745. 18056 PUBLIC int do_alarm()
  746. 18057 {
  747. 18058 /* Perform the alarm(seconds) system call. */
  748. 18059
  749. 18060   return(set_alarm(who, seconds));
  750. 18061 }
  751. 18064 /*===========================================================================*
  752. 18065  *                              set_alarm                                    *
  753. 18066  *===========================================================================*/
  754. 18067 PUBLIC int set_alarm(proc_nr, sec)
  755. 18068 int proc_nr;                    /* process that wants the alarm */
  756. 18069 int sec;                        /* how many seconds delay before the signal */
  757. 18070 {
  758. 18071 /* This routine is used by do_alarm() to set the alarm timer.  It is also used
  759. 18072  * to turn the timer off when a process exits with the timer still on.
  760. 18073  */
  761. 18074
  762. 18075   message m_sig;
  763. 18076   int remaining;
  764. 18077
  765. 18078   if (sec != 0)
  766. 18079         mproc[proc_nr].mp_flags |= ALARM_ON;
  767. 18080   else
  768. 18081         mproc[proc_nr].mp_flags &= ~ALARM_ON;
  769. 18082
  770. 18083   /* Tell the clock task to provide a signal message when the time comes.
  771. 18084    *
  772. 18085    * Large delays cause a lot of problems.  First, the alarm system call
  773. 18086    * takes an unsigned seconds count and the library has cast it to an int.
  774. 18087    * That probably works, but on return the library will convert "negative"
  775. 18088    * unsigneds to errors.  Presumably no one checks for these errors, so
  776. 18089    * force this call through.  Second, If unsigned and long have the same
  777. 18090    * size, converting from seconds to ticks can easily overflow.  Finally,
  778. 18091    * the kernel has similar overflow bugs adding ticks.
  779. 18092    *
  780. 18093    * Fixing this requires a lot of ugly casts to fit the wrong interface
  781. 18094    * types and to avoid overflow traps.  DELTA_TICKS has the right type
  782. .Ep 252 src/mm/signal.c
  783. 18095    * (clock_t) although it is declared as long.  How can variables like
  784. 18096    * this be declared properly without combinatorial explosion of message
  785. 18097    * types?
  786. 18098    */
  787. 18099   m_sig.m_type = SET_ALARM;
  788. 18100   m_sig.CLOCK_PROC_NR = proc_nr;
  789. 18101   m_sig.DELTA_TICKS = (clock_t) (HZ * (unsigned long) (unsigned) sec);
  790. 18102   if ( (unsigned long) m_sig.DELTA_TICKS / HZ != (unsigned) sec)
  791. 18103         m_sig.DELTA_TICKS = LONG_MAX;   /* eternity (really CLOCK_T_MAX) */
  792. 18104   if (sendrec(CLOCK, &m_sig) != OK) panic("alarm er", NO_NUM);
  793. 18105   remaining = (int) m_sig.SECONDS_LEFT;
  794. 18106   if (remaining != m_sig.SECONDS_LEFT || remaining < 0)
  795. 18107         remaining = INT_MAX;    /* true value is not representable */
  796. 18108   return(remaining);
  797. 18109 }
  798. 18112 /*===========================================================================*
  799. 18113  *                              do_pause                                     *
  800. 18114  *===========================================================================*/
  801. 18115 PUBLIC int do_pause()
  802. 18116 {
  803. 18117 /* Perform the pause() system call. */
  804. 18118
  805. 18119   mp->mp_flags |= PAUSED;
  806. 18120   dont_reply = TRUE;
  807. 18121   return(OK);
  808. 18122 }
  809. 18125 /*=====================================================================*
  810. 18126  *                          do_reboot                                  *
  811. 18127  *=====================================================================*/
  812. 18128 PUBLIC int do_reboot()
  813. 18129 {
  814. 18130   register struct mproc *rmp = mp;
  815. 18131   char monitor_code[64];
  816. 18132
  817. 18133   if (rmp->mp_effuid != SUPER_USER)   return EPERM;
  818. 18134
  819. 18135   switch (reboot_flag) {
  820. 18136   case RBT_HALT:
  821. 18137   case RBT_REBOOT:
  822. 18138   case RBT_PANIC:
  823. 18139   case RBT_RESET:
  824. 18140         break;
  825. 18141   case RBT_MONITOR:
  826. 18142         if (reboot_size > sizeof(monitor_code)) return EINVAL;
  827. 18143         memset(monitor_code, 0, sizeof(monitor_code));
  828. 18144         if (sys_copy(who, D, (phys_bytes) reboot_code,
  829. 18145                 MM_PROC_NR, D, (phys_bytes) monitor_code,
  830. 18146                 (phys_bytes) reboot_size) != OK) return EFAULT;
  831. 18147         if (monitor_code[sizeof(monitor_code)-1] != 0) return EINVAL;
  832. 18148         break;
  833. 18149   default:
  834. 18150         return EINVAL;
  835. 18151   }
  836. 18152
  837. 18153   /* Kill all processes except init. */
  838. 18154   check_sig(-1, SIGKILL);
  839. .Op 253 src/mm/signal.c
  840. 18155
  841. 18156   tell_fs(EXIT, INIT_PROC_NR, 0, 0);    /* cleanup init */
  842. 18157
  843. 18158   tell_fs(SYNC,0,0,0);
  844. 18159
  845. 18160   sys_abort(reboot_flag, monitor_code);
  846. 18161   /* NOTREACHED */
  847. 18162 }
  848. 18165 /*===========================================================================*
  849. 18166  *                              sig_proc                                     *
  850. 18167  *===========================================================================*/
  851. 18168 PUBLIC void sig_proc(rmp, signo)
  852. 18169 register struct mproc *rmp;     /* pointer to the process to be signaled */
  853. 18170 int signo;                      /* signal to send to process (1 to _NSIG) */
  854. 18171 {
  855. 18172 /* Send a signal to a process.  Check to see if the signal is to be caught,
  856. 18173  * ignored, or blocked.  If the signal is to be caught, coordinate with
  857. 18174  * KERNEL to push a sigcontext structure and a sigframe structure onto
  858. 18175  * the catcher's stack.  Also, KERNEL will reset the program counter and
  859. 18176  * stack pointer, so that when the process next runs, it will be executing
  860. 18177  * the signal handler.  When the signal handler returns,  sigreturn(2)
  861. 18178  * will be called.  Then KERNEL will restore the signal context from the
  862. 18179  * sigcontext structure.
  863. 18180  *
  864. 18181  * If there is insufficient stack space, kill the process.
  865. 18182  */
  866. 18183
  867. 18184   vir_bytes new_sp;
  868. 18185   int slot;
  869. 18186   int sigflags;
  870. 18187   struct sigmsg sm;
  871. 18188
  872. 18189   slot = (int) (rmp - mproc);
  873. 18190   if (!(rmp->mp_flags & IN_USE)) {
  874. 18191         printf("MM: signal %d sent to dead process %dn", signo, slot);
  875. 18192         panic("", NO_NUM);
  876. 18193   }
  877. 18194   if (rmp->mp_flags & HANGING) {
  878. 18195         printf("MM: signal %d sent to HANGING process %dn", signo, slot);
  879. 18196         panic("", NO_NUM);
  880. 18197   }
  881. 18198   if (rmp->mp_flags & TRACED && signo != SIGKILL) {
  882. 18199         /* A traced process has special handling. */
  883. 18200         unpause(slot);
  884. 18201         stop_proc(rmp, signo);  /* a signal causes it to stop */
  885. 18202         return;
  886. 18203   }
  887. 18204   /* Some signals are ignored by default. */
  888. 18205   if (sigismember(&rmp->mp_ignore, signo)) return; 
  889. 18206
  890. 18207   if (sigismember(&rmp->mp_sigmask, signo)) {
  891. 18208         /* Signal should be blocked. */
  892. 18209         sigaddset(&rmp->mp_sigpending, signo);
  893. 18210         return;
  894. 18211   }
  895. 18212   sigflags = rmp->mp_sigact[signo].sa_flags;
  896. 18213   if (sigismember(&rmp->mp_catch, signo)) {
  897. 18214         if (rmp->mp_flags & SIGSUSPENDED)
  898. .Ep 254 src/mm/signal.c
  899. 18215                 sm.sm_mask = rmp->mp_sigmask2;
  900. 18216         else
  901. 18217                 sm.sm_mask = rmp->mp_sigmask;
  902. 18218         sm.sm_signo = signo;
  903. 18219         sm.sm_sighandler = (vir_bytes) rmp->mp_sigact[signo].sa_handler;
  904. 18220         sm.sm_sigreturn = rmp->mp_sigreturn;
  905. 18221         sys_getsp(slot, &new_sp);
  906. 18222         sm.sm_stkptr = new_sp;
  907. 18223
  908. 18224         /* Make room for the sigcontext and sigframe struct. */
  909. 18225         new_sp -= sizeof(struct sigcontext)
  910. 18226                                  + 3 * sizeof(char *) + 2 * sizeof(int);
  911. 18227
  912. 18228         if (adjust(rmp, rmp->mp_seg[D].mem_len, new_sp) != OK)
  913. 18229                 goto doterminate;
  914. 18230
  915. 18231         rmp->mp_sigmask |= rmp->mp_sigact[signo].sa_mask;
  916. 18232         if (sigflags & SA_NODEFER)
  917. 18233                 sigdelset(&rmp->mp_sigmask, signo);
  918. 18234         else
  919. 18235                 sigaddset(&rmp->mp_sigmask, signo);
  920. 18236
  921. 18237         if (sigflags & SA_RESETHAND) {
  922. 18238                 sigdelset(&rmp->mp_catch, signo);
  923. 18239                 rmp->mp_sigact[signo].sa_handler = SIG_DFL;
  924. 18240         }
  925. 18241
  926. 18242         sys_sendsig(slot, &sm);
  927. 18243         sigdelset(&rmp->mp_sigpending, signo);
  928. 18244         /* If process is hanging on PAUSE, WAIT, SIGSUSPEND, tty, pipe, etc.,
  929. 18245          * release it.
  930. 18246          */
  931. 18247         unpause(slot);
  932. 18248         return;
  933. 18249   }
  934. 18250 doterminate:
  935. 18251   /* Signal should not or cannot be caught.  Terminate the process. */
  936. 18252   rmp->mp_sigstatus = (char) signo;
  937. 18253   if (sigismember(&core_sset, signo)) {
  938. 18254         /* Switch to the user's FS environment and dump core. */
  939. 18255         tell_fs(CHDIR, slot, FALSE, 0);
  940. 18256         dump_core(rmp);
  941. 18257   }
  942. 18258   mm_exit(rmp, 0);              /* terminate process */
  943. 18259 }
  944. 18262 /*===========================================================================*
  945. 18263  *                              check_sig                                    *
  946. 18264  *===========================================================================*/
  947. 18265 PUBLIC int check_sig(proc_id, signo)
  948. 18266 pid_t proc_id;                  /* pid of proc to sig, or 0 or -1, or -pgrp */
  949. 18267 int signo;                      /* signal to send to process (0 to _NSIG) */
  950. 18268 {
  951. 18269 /* Check to see if it is possible to send a signal.  The signal may have to be
  952. 18270  * sent to a group of processes.  This routine is invoked by the KILL system
  953. 18271  * call, and also when the kernel catches a DEL or other signal.
  954. 18272  */
  955. 18273
  956. 18274   register struct mproc *rmp;
  957. .Op 255 src/mm/signal.c
  958. 18275   int count;                    /* count # of signals sent */
  959. 18276   int error_code;
  960. 18277
  961. 18278   if (signo < 0 || signo > _NSIG) return(EINVAL);
  962. 18279
  963. 18280   /* Return EINVAL for attempts to send SIGKILL to INIT alone. */
  964. 18281   if (proc_id == INIT_PID && signo == SIGKILL) return(EINVAL);
  965. 18282
  966. 18283   /* Search the proc table for processes to signal.  (See forkexit.c about
  967. 18284    * pid magic.)
  968. 18285    */
  969. 18286   count = 0;
  970. 18287   error_code = ESRCH;
  971. 18288   for (rmp = &mproc[INIT_PROC_NR]; rmp < &mproc[NR_PROCS]; rmp++) {
  972. 18289         if ( (rmp->mp_flags & IN_USE) == 0) continue;
  973. 18290         if (rmp->mp_flags & HANGING && signo != 0) continue;
  974. 18291
  975. 18292         /* Check for selection. */
  976. 18293         if (proc_id > 0 && proc_id != rmp->mp_pid) continue;
  977. 18294         if (proc_id == 0 && mp->mp_procgrp != rmp->mp_procgrp) continue;
  978. 18295         if (proc_id == -1 && rmp->mp_pid == INIT_PID) continue;
  979. 18296         if (proc_id < -1 && rmp->mp_procgrp != -proc_id) continue;
  980. 18297
  981. 18298         /* Check for permission. */
  982. 18299         if (mp->mp_effuid != SUPER_USER
  983. 18300             && mp->mp_realuid != rmp->mp_realuid
  984. 18301             && mp->mp_effuid != rmp->mp_realuid
  985. 18302             && mp->mp_realuid != rmp->mp_effuid
  986. 18303             && mp->mp_effuid != rmp->mp_effuid) {
  987. 18304                 error_code = EPERM;
  988. 18305                 continue;
  989. 18306         }
  990. 18307
  991. 18308         count++;
  992. 18309         if (signo == 0) continue;
  993. 18310
  994. 18311         /* 'sig_proc' will handle the disposition of the signal.  The
  995. 18312          * signal may be caught, blocked, ignored, or cause process
  996. 18313          * termination, possibly with core dump.
  997. 18314          */
  998. 18315         sig_proc(rmp, signo);
  999. 18316
  1000. 18317         if (proc_id > 0) break; /* only one process being signaled */
  1001. 18318   }
  1002. 18319
  1003. 18320   /* If the calling process has killed itself, don't reply. */
  1004. 18321   if ((mp->mp_flags & IN_USE) == 0 || (mp->mp_flags & HANGING))
  1005. 18322         dont_reply = TRUE;
  1006. 18323   return(count > 0 ? OK : error_code);
  1007. 18324 }
  1008. 18327 /*===========================================================================*
  1009. 18328  *                               check_pending                               *
  1010. 18329  *===========================================================================*/
  1011. 18330 PRIVATE void check_pending()
  1012. 18331 {
  1013. 18332   /* Check to see if any pending signals have been unblocked.  The
  1014. 18333    * first such signal found is delivered.
  1015. 18334    *
  1016. .Ep 256 src/mm/signal.c
  1017. 18335    * If multiple pending unmasked signals are found, they will be
  1018. 18336    * delivered sequentially.
  1019. 18337    *
  1020. 18338    * There are several places in this file where the signal mask is
  1021. 18339    * changed.  At each such place, check_pending() should be called to
  1022. 18340    * check for newly unblocked signals.
  1023. 18341    */
  1024. 18342
  1025. 18343   int i;
  1026. 18344
  1027. 18345   for (i = 1; i < _NSIG; i++) {
  1028. 18346         if (sigismember(&mp->mp_sigpending, i) &&
  1029. 18347                 !sigismember(&mp->mp_sigmask, i)) {
  1030. 18348                 sigdelset(&mp->mp_sigpending, i);
  1031. 18349                 sig_proc(mp, i);
  1032. 18350                 break;
  1033. 18351         }
  1034. 18352   }
  1035. 18353 }
  1036. 18356 /*===========================================================================*
  1037. 18357  *                              unpause                                      *
  1038. 18358  *===========================================================================*/
  1039. 18359 PRIVATE void unpause(pro)
  1040. 18360 int pro;                        /* which process number */
  1041. 18361 {
  1042. 18362 /* A signal is to be sent to a process.  If that process is hanging on a
  1043. 18363  * system call, the system call must be terminated with EINTR.  Possible
  1044. 18364  * calls are PAUSE, WAIT, READ and WRITE, the latter two for pipes and ttys.
  1045. 18365  * First check if the process is hanging on an MM call.  If not, tell FS,
  1046. 18366  * so it can check for READs and WRITEs from pipes, ttys and the like.
  1047. 18367  */
  1048. 18368
  1049. 18369   register struct mproc *rmp;
  1050. 18370
  1051. 18371   rmp = &mproc[pro];
  1052. 18372
  1053. 18373   /* Check to see if process is hanging on a PAUSE call. */
  1054. 18374   if ( (rmp->mp_flags & PAUSED) && (rmp->mp_flags & HANGING) == 0) {
  1055. 18375         rmp->mp_flags &= ~PAUSED;
  1056. 18376         reply(pro, EINTR, 0, NIL_PTR);
  1057. 18377         return;
  1058. 18378   }
  1059. 18379
  1060. 18380   /* Check to see if process is hanging on a WAIT call. */
  1061. 18381   if ( (rmp->mp_flags & WAITING) && (rmp->mp_flags & HANGING) == 0) {
  1062. 18382         rmp->mp_flags &= ~WAITING;
  1063. 18383         reply(pro, EINTR, 0, NIL_PTR);
  1064. 18384         return;
  1065. 18385   }
  1066. 18386
  1067. 18387   /* Check to see if process is hanging on a SIGSUSPEND call. */
  1068. 18388   if ((rmp->mp_flags & SIGSUSPENDED) && (rmp->mp_flags & HANGING) == 0) {
  1069. 18389         rmp->mp_flags &= ~SIGSUSPENDED;
  1070. 18390         reply(pro, EINTR, 0, NIL_PTR);
  1071. 18391         return;
  1072. 18392   }
  1073. 18393
  1074. 18394   /* Process is not hanging on an MM call.  Ask FS to take a look. */
  1075. .Op 257 src/mm/signal.c
  1076. 18395         tell_fs(UNPAUSE, pro, 0, 0);
  1077. 18396 }
  1078. 18399 /*===========================================================================*
  1079. 18400  *                              dump_core                                    *
  1080. 18401  *===========================================================================*/
  1081. 18402 PRIVATE void dump_core(rmp)
  1082. 18403 register struct mproc *rmp;     /* whose core is to be dumped */
  1083. 18404 {
  1084. 18405 /* Make a core dump on the file "core", if possible. */
  1085. 18406
  1086. 18407   int fd, fake_fd, nr_written, seg, slot;
  1087. 18408   char *buf;
  1088. 18409   vir_bytes current_sp;
  1089. 18410   phys_bytes left;              /* careful; 64K might overflow vir_bytes */
  1090. 18411   unsigned nr_to_write;         /* unsigned for arg to write() but < INT_MAX */
  1091. 18412   long trace_data, trace_off;
  1092. 18413
  1093. 18414   slot = (int) (rmp - mproc);
  1094. 18415
  1095. 18416   /* Can core file be written?  We are operating in the user's FS environment,
  1096. 18417    * so no special permission checks are needed.
  1097. 18418    */
  1098. 18419   if (rmp->mp_realuid != rmp->mp_effuid) return;
  1099. 18420   if ( (fd = creat(core_name, CORE_MODE)) < 0) return;
  1100. 18421   rmp->mp_sigstatus |= DUMPED;
  1101. 18422
  1102. 18423   /* Make sure the stack segment is up to date.
  1103. 18424    * We don't want adjust() to fail unless current_sp is preposterous,
  1104. 18425    * but it might fail due to safety checking.  Also, we don't really want 
  1105. 18426    * the adjust() for sending a signal to fail due to safety checking.  
  1106. 18427    * Maybe make SAFETY_BYTES a parameter.
  1107. 18428    */
  1108. 18429   sys_getsp(slot, &current_sp);
  1109. 18430   adjust(rmp, rmp->mp_seg[D].mem_len, current_sp);
  1110. 18431
  1111. 18432   /* Write the memory map of all segments to begin the core file. */
  1112. 18433   if (write(fd, (char *) rmp->mp_seg, (unsigned) sizeof rmp->mp_seg)
  1113. 18434       != (unsigned) sizeof rmp->mp_seg) {
  1114. 18435         close(fd);
  1115. 18436         return;
  1116. 18437   }
  1117. 18438
  1118. 18439   /* Write out the whole kernel process table entry to get the regs. */
  1119. 18440   trace_off = 0;
  1120. 18441   while (sys_trace(3, slot, trace_off, &trace_data) == OK) {
  1121. 18442         if (write(fd, (char *) &trace_data, (unsigned) sizeof (long))
  1122. 18443             != (unsigned) sizeof (long)) {
  1123. 18444                 close(fd);
  1124. 18445                 return;
  1125. 18446         }
  1126. 18447         trace_off += sizeof (long);
  1127. 18448   }
  1128. 18449
  1129. 18450   /* Loop through segments and write the segments themselves out. */
  1130. 18451   for (seg = 0; seg < NR_SEGS; seg++) {
  1131. 18452         buf = (char *) ((vir_bytes) rmp->mp_seg[seg].mem_vir << CLICK_SHIFT);
  1132. 18453         left = (phys_bytes) rmp->mp_seg[seg].mem_len << CLICK_SHIFT;
  1133. 18454         fake_fd = (slot << 8) | (seg << 6) | fd;
  1134. .Ep 258 src/mm/signal.c
  1135. 18455
  1136. 18456         /* Loop through a segment, dumping it. */
  1137. 18457         while (left != 0) {
  1138. 18458                 nr_to_write = (unsigned) MIN(left, DUMP_SIZE);
  1139. 18459                 if ( (nr_written = write(fake_fd, buf, nr_to_write)) < 0) {
  1140. 18460                         close(fd);
  1141. 18461                         return;
  1142. 18462                 }
  1143. 18463                 buf += nr_written;
  1144. 18464                 left -= nr_written;
  1145. 18465         }
  1146. 18466   }
  1147. 18467   close(fd);
  1148. 18468 }
  1149. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1150. src/mm/getset.c    
  1151. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1152. 18500 /* This file handles the 4 system calls that get and set uids and gids.
  1153. 18501  * It also handles getpid(), setsid(), and getpgrp().  The code for each
  1154. 18502  * one is so tiny that it hardly seemed worthwhile to make each a separate
  1155. 18503  * function.
  1156. 18504  */
  1157. 18505
  1158. 18506 #include "mm.h"
  1159. 18507 #include <minix/callnr.h>
  1160. 18508 #include <signal.h>
  1161. 18509 #include "mproc.h"
  1162. 18510 #include "param.h"
  1163. 18511
  1164. 18512 /*===========================================================================*
  1165. 18513  *                              do_getset                                    *
  1166. 18514  *===========================================================================*/
  1167. 18515 PUBLIC int do_getset()
  1168. 18516 {
  1169. 18517 /* Handle GETUID, GETGID, GETPID, GETPGRP, SETUID, SETGID, SETSID.  The four
  1170. 18518  * GETs and SETSID return their primary results in 'r'.  GETUID, GETGID, and
  1171. 18519  * GETPID also return secondary results (the effective IDs, or the parent
  1172. 18520  * process ID) in 'result2', which is returned to the user.
  1173. 18521  */
  1174. 18522
  1175. 18523   register struct mproc *rmp = mp;
  1176. 18524   register int r;
  1177. 18525
  1178. 18526   switch(mm_call) {
  1179. 18527         case GETUID:
  1180. 18528                 r = rmp->mp_realuid;
  1181. 18529                 result2 = rmp->mp_effuid;
  1182. 18530                 break;
  1183. 18531
  1184. 18532         case GETGID:
  1185. 18533                 r = rmp->mp_realgid;
  1186. 18534                 result2 = rmp->mp_effgid;
  1187. 18535                 break;
  1188. 18536
  1189. 18537         case GETPID:
  1190. 18538                 r = mproc[who].mp_pid;
  1191. 18539                 result2 = mproc[rmp->mp_parent].mp_pid;
  1192. .Op 259 src/mm/getset.c
  1193. 18540                 break;
  1194. 18541
  1195. 18542         case SETUID:
  1196. 18543                 if (rmp->mp_realuid != usr_id && rmp->mp_effuid != SUPER_USER)
  1197. 18544                         return(EPERM);
  1198. 18545                 rmp->mp_realuid = usr_id;
  1199. 18546                 rmp->mp_effuid = usr_id;
  1200. 18547                 tell_fs(SETUID, who, usr_id, usr_id);
  1201. 18548                 r = OK;
  1202. 18549                 break;
  1203. 18550
  1204. 18551         case SETGID:
  1205. 18552                 if (rmp->mp_realgid != grpid && rmp->mp_effuid != SUPER_USER)
  1206. 18553                         return(EPERM);
  1207. 18554                 rmp->mp_realgid = grpid;
  1208. 18555                 rmp->mp_effgid = grpid;
  1209. 18556                 tell_fs(SETGID, who, grpid, grpid);
  1210. 18557                 r = OK;
  1211. 18558                 break;
  1212. 18559
  1213. 18560         case SETSID:
  1214. 18561                 if (rmp->mp_procgrp == rmp->mp_pid) return(EPERM);
  1215. 18562                 rmp->mp_procgrp = rmp->mp_pid;
  1216. 18563                 tell_fs(SETSID, who, 0, 0);
  1217. 18564                 /*FALL THROUGH*/
  1218. 18565
  1219. 18566         case GETPGRP:
  1220. 18567                 r = rmp->mp_procgrp;
  1221. 18568                 break;
  1222. 18569
  1223. 18570         default:
  1224. 18571                 r = EINVAL;
  1225. 18572                 break;  
  1226. 18573   }
  1227. 18574   return(r);
  1228. 18575 }
  1229. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1230. src/mm/trace.c    
  1231. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1232. 18600 /* This file handles the memory manager's part of debugging, using the 
  1233. 18601  * ptrace system call. Most of the commands are passed on to the system
  1234. 18602  * task for completion.
  1235. 18603  *
  1236. 18604  * The debugging commands available are:
  1237. 18605  * T_STOP       stop the process 
  1238. 18606  * T_OK         enable tracing by parent for this process
  1239. 18607  * T_GETINS     return value from instruction space 
  1240. 18608  * T_GETDATA    return value from data space 
  1241. 18609  * T_GETUSER    return value from user process table
  1242. 18610  * T_SETINS     set value in instruction space
  1243. 18611  * T_SETDATA    set value in data space
  1244. 18612  * T_SETUSER    set value in user process table 
  1245. 18613  * T_RESUME     resume execution 
  1246. 18614  * T_EXIT       exit
  1247. .Ep 260 src/mm/trace.c
  1248. 18615  * T_STEP       set trace bit 
  1249. 18616  * 
  1250. 18617  * The T_OK and T_EXIT commands are handled here, and the T_RESUME and
  1251. 18618  * T_STEP commands are partially handled here and completed by the system
  1252. 18619  * task. The rest are handled entirely by the system task. 
  1253. 18620  */
  1254. 18621
  1255. 18622 #include "mm.h"
  1256. 18623 #include <sys/ptrace.h>
  1257. 18624 #include <signal.h>
  1258. 18625 #include "mproc.h"
  1259. 18626 #include "param.h"
  1260. 18627
  1261. 18628 #define NIL_MPROC       ((struct mproc *) 0)
  1262. 18629
  1263. 18630 FORWARD _PROTOTYPE( struct mproc *findproc, (pid_t lpid) );
  1264. 18631
  1265. 18632 /*===========================================================================*
  1266. 18633  *                              do_trace                                     *
  1267. 18634  *===========================================================================*/
  1268. 18635 PUBLIC int do_trace()
  1269. 18636 {
  1270. 18637   register struct mproc *child;
  1271. 18638
  1272. 18639   /* the T_OK call is made by the child fork of the debugger before it execs  
  1273. 18640    * the process to be traced
  1274. 18641    */
  1275. 18642   if (request == T_OK) {/* enable tracing by parent for this process */
  1276. 18643         mp->mp_flags |= TRACED;
  1277. 18644         mm_out.m2_l2 = 0;
  1278. 18645         return(OK);
  1279. 18646   }
  1280. 18647   if ((child = findproc(pid)) == NIL_MPROC || !(child->mp_flags & STOPPED)) {
  1281. 18648         return(ESRCH);
  1282. 18649   }
  1283. 18650   /* all the other calls are made by the parent fork of the debugger to 
  1284. 18651    * control execution of the child
  1285. 18652    */
  1286. 18653   switch (request) {
  1287. 18654   case T_EXIT:          /* exit */
  1288. 18655         mm_exit(child, (int)data);
  1289. 18656         mm_out.m2_l2 = 0;
  1290. 18657         return(OK);
  1291. 18658   case T_RESUME: 
  1292. 18659   case T_STEP:          /* resume execution */
  1293. 18660         if (data < 0 || data > _NSIG) return(EIO);
  1294. 18661         if (data > 0) {         /* issue signal */
  1295. 18662                 child->mp_flags &= ~TRACED;  /* so signal is not diverted */
  1296. 18663                 sig_proc(child, (int) data);
  1297. 18664                 child->mp_flags |= TRACED;
  1298. 18665         }
  1299. 18666         child->mp_flags &= ~STOPPED;
  1300. 18667         break;
  1301. 18668   }
  1302. 18669   if (sys_trace(request, (int) (child - mproc), taddr, &data) != OK)
  1303. 18670         return(-errno);
  1304. 18671   mm_out.m2_l2 = data;
  1305. 18672   return(OK);
  1306. 18673 }
  1307. .Op 261 src/mm/trace.c
  1308. 18675 /*===========================================================================*
  1309. 18676  *                              findproc                                     *
  1310. 18677  *===========================================================================*/
  1311. 18678 PRIVATE struct mproc *findproc(lpid)
  1312. 18679 pid_t lpid;
  1313. 18680 {
  1314. 18681   register struct mproc *rmp;
  1315. 18682
  1316. 18683   for (rmp = &mproc[INIT_PROC_NR + 1]; rmp < &mproc[NR_PROCS]; rmp++)
  1317. 18684         if (rmp->mp_flags & IN_USE && rmp->mp_pid == lpid) return(rmp);
  1318. 18685   return(NIL_MPROC);
  1319. 18686 }
  1320. 18688 /*===========================================================================*
  1321. 18689  *                              stop_proc                                    *
  1322. 18690  *===========================================================================*/
  1323. 18691 PUBLIC void stop_proc(rmp, signo)
  1324. 18692 register struct mproc *rmp;
  1325. 18693 int signo;
  1326. 18694 {
  1327. 18695 /* A traced process got a signal so stop it. */
  1328. 18696
  1329. 18697   register struct mproc *rpmp = mproc + rmp->mp_parent;
  1330. 18698
  1331. 18699   if (sys_trace(-1, (int) (rmp - mproc), 0L, (long *) 0) != OK) return;
  1332. 18700   rmp->mp_flags |= STOPPED;
  1333. 18701   if (rpmp->mp_flags & WAITING) {
  1334. 18702         rpmp->mp_flags &= ~WAITING;     /* parent is no longer waiting */
  1335. 18703         reply(rmp->mp_parent, rmp->mp_pid, 0177 | (signo << 8), NIL_PTR);
  1336. 18704   } else {
  1337. 18705         rmp->mp_sigstatus = signo;
  1338. 18706   }
  1339. 18707   return;
  1340. 18708 }
  1341. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1342. src/mm/alloc.c    
  1343. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1344. 18800 /* This file is concerned with allocating and freeing arbitrary-size blocks of
  1345. 18801  * physical memory on behalf of the FORK and EXEC system calls.  The key data
  1346. 18802  * structure used is the hole table, which maintains a list of holes in memory.
  1347. 18803  * It is kept sorted in order of increasing memory address. The addresses
  1348. 18804  * it contains refer to physical memory, starting at absolute address 0
  1349. 18805  * (i.e., they are not relative to the start of MM).  During system
  1350. 18806  * initialization, that part of memory containing the interrupt vectors,
  1351. 18807  * kernel, and MM are "allocated" to mark them as not available and to
  1352. 18808  * remove them from the hole list.
  1353. 18809  *
  1354. 18810  * The entry points into this file are:
  1355. 18811  *   alloc_mem: allocate a given sized chunk of memory
  1356. 18812  *   free_mem:  release a previously allocated chunk of memory
  1357. 18813  *   mem_init:  initialize the tables when MM start up
  1358. 18814  *   max_hole:  returns the largest hole currently available
  1359. 18815  */
  1360. 18816
  1361. 18817 #include "mm.h"
  1362. 18818 #include <minix/com.h>
  1363. 18819
  1364. .Ep 262 src/mm/alloc.c
  1365. 18820 #define NR_HOLES         128    /* max # entries in hole table */
  1366. 18821 #define NIL_HOLE (struct hole *) 0
  1367. 18822
  1368. 18823 PRIVATE struct hole {
  1369. 18824   phys_clicks h_base;           /* where does the hole begin? */
  1370. 18825   phys_clicks h_len;            /* how big is the hole? */
  1371. 18826   struct hole *h_next;          /* pointer to next entry on the list */
  1372. 18827 } hole[NR_HOLES];
  1373. 18828
  1374. 18829
  1375. 18830 PRIVATE struct hole *hole_head; /* pointer to first hole */
  1376. 18831 PRIVATE struct hole *free_slots;        /* ptr to list of unused table slots */
  1377. 18832
  1378. 18833 FORWARD _PROTOTYPE( void del_slot, (struct hole *prev_ptr, struct hole *hp) );
  1379. 18834 FORWARD _PROTOTYPE( void merge, (struct hole *hp)                           );
  1380. 18835
  1381. 18836
  1382. 18837 /*===========================================================================*
  1383. 18838  *                              alloc_mem                                    *
  1384. 18839  *===========================================================================*/
  1385. 18840 PUBLIC phys_clicks alloc_mem(clicks)
  1386. 18841 phys_clicks clicks;             /* amount of memory requested */
  1387. 18842 {
  1388. 18843 /* Allocate a block of memory from the free list using first fit. The block
  1389. 18844  * consists of a sequence of contiguous bytes, whose length in clicks is
  1390. 18845  * given by 'clicks'.  A pointer to the block is returned.  The block is
  1391. 18846  * always on a click boundary.  This procedure is called when memory is
  1392. 18847  * needed for FORK or EXEC.
  1393. 18848  */
  1394. 18849
  1395. 18850   register struct hole *hp, *prev_ptr;
  1396. 18851   phys_clicks old_base;
  1397. 18852
  1398. 18853   hp = hole_head;
  1399. 18854   while (hp != NIL_HOLE) {
  1400. 18855         if (hp->h_len >= clicks) {
  1401. 18856                 /* We found a hole that is big enough.  Use it. */
  1402. 18857                 old_base = hp->h_base;  /* remember where it started */
  1403. 18858                 hp->h_base += clicks;   /* bite a piece off */
  1404. 18859                 hp->h_len -= clicks;    /* ditto */
  1405. 18860
  1406. 18861                 /* If hole is only partly used, reduce size and return. */
  1407. 18862                 if (hp->h_len != 0) return(old_base);
  1408. 18863
  1409. 18864                 /* The entire hole has been used up.  Manipulate free list. */
  1410. 18865                 del_slot(prev_ptr, hp);
  1411. 18866                 return(old_base);
  1412. 18867         }
  1413. 18868
  1414. 18869         prev_ptr = hp;
  1415. 18870         hp = hp->h_next;
  1416. 18871   }
  1417. 18872   return(NO_MEM);
  1418. 18873 }
  1419. 18876 /*===========================================================================*
  1420. 18877  *                              free_mem                                     *
  1421. 18878  *===========================================================================*/
  1422. 18879 PUBLIC void free_mem(base, clicks)
  1423. .Op 263 src/mm/alloc.c
  1424. 18880 phys_clicks base;               /* base address of block to free */
  1425. 18881 phys_clicks clicks;             /* number of clicks to free */
  1426. 18882 {
  1427. 18883 /* Return a block of free memory to the hole list.  The parameters tell where
  1428. 18884  * the block starts in physical memory and how big it is.  The block is added
  1429. 18885  * to the hole list.  If it is contiguous with an existing hole on either end,
  1430. 18886  * it is merged with the hole or holes.
  1431. 18887  */
  1432. 18888
  1433. 18889   register struct hole *hp, *new_ptr, *prev_ptr;
  1434. 18890
  1435. 18891   if (clicks == 0) return;
  1436. 18892   if ( (new_ptr = free_slots) == NIL_HOLE) panic("Hole table full", NO_NUM);
  1437. 18893   new_ptr->h_base = base;
  1438. 18894   new_ptr->h_len = clicks;
  1439. 18895   free_slots = new_ptr->h_next;
  1440. 18896   hp = hole_head;
  1441. 18897
  1442. 18898   /* If this block's address is numerically less than the lowest hole currently
  1443. 18899    * available, or if no holes are currently available, put this hole on the
  1444. 18900    * front of the hole list.
  1445. 18901    */
  1446. 18902   if (hp == NIL_HOLE || base <= hp->h_base) {
  1447. 18903         /* Block to be freed goes on front of the hole list. */
  1448. 18904         new_ptr->h_next = hp;
  1449. 18905         hole_head = new_ptr;
  1450. 18906         merge(new_ptr);
  1451. 18907         return;
  1452. 18908   }
  1453. 18909
  1454. 18910   /* Block to be returned does not go on front of hole list. */
  1455. 18911   while (hp != NIL_HOLE && base > hp->h_base) {
  1456. 18912         prev_ptr = hp;
  1457. 18913         hp = hp->h_next;
  1458. 18914   }
  1459. 18915
  1460. 18916   /* We found where it goes.  Insert block after 'prev_ptr'. */
  1461. 18917   new_ptr->h_next = prev_ptr->h_next;
  1462. 18918   prev_ptr->h_next = new_ptr;
  1463. 18919   merge(prev_ptr);              /* sequence is 'prev_ptr', 'new_ptr', 'hp' */
  1464. 18920 }
  1465. 18923 /*===========================================================================*
  1466. 18924  *                              del_slot                                     *
  1467. 18925  *===========================================================================*/
  1468. 18926 PRIVATE void del_slot(prev_ptr, hp)
  1469. 18927 register struct hole *prev_ptr; /* pointer to hole entry just ahead of 'hp' */
  1470. 18928 register struct hole *hp;       /* pointer to hole entry to be removed */
  1471. 18929 {
  1472. 18930 /* Remove an entry from the hole list.  This procedure is called when a
  1473. 18931  * request to allocate memory removes a hole in its entirety, thus reducing
  1474. 18932  * the numbers of holes in memory, and requiring the elimination of one
  1475. 18933  * entry in the hole list.
  1476. 18934  */
  1477. 18935
  1478. 18936   if (hp == hole_head)
  1479. 18937         hole_head = hp->h_next;
  1480. 18938   else
  1481. 18939         prev_ptr->h_next = hp->h_next;
  1482. .Ep 264 src/mm/alloc.c
  1483. 18940
  1484. 18941   hp->h_next = free_slots;
  1485. 18942   free_slots = hp;
  1486. 18943 }
  1487. 18946 /*===========================================================================*
  1488. 18947  *                              merge                                        *
  1489. 18948  *===========================================================================*/
  1490. 18949 PRIVATE void merge(hp)
  1491. 18950 register struct hole *hp;       /* ptr to hole to merge with its successors */
  1492. 18951 {
  1493. 18952 /* Check for contiguous holes and merge any found.  Contiguous holes can occur
  1494. 18953  * when a block of memory is freed, and it happens to abut another hole on
  1495. 18954  * either or both ends.  The pointer 'hp' points to the first of a series of
  1496. 18955  * three holes that can potentially all be merged together.
  1497. 18956  */
  1498. 18957
  1499. 18958   register struct hole *next_ptr;
  1500. 18959
  1501. 18960   /* If 'hp' points to the last hole, no merging is possible.  If it does not,
  1502. 18961    * try to absorb its successor into it and free the successor's table entry.
  1503. 18962    */
  1504. 18963   if ( (next_ptr = hp->h_next) == NIL_HOLE) return;
  1505. 18964   if (hp->h_base + hp->h_len == next_ptr->h_base) {
  1506. 18965         hp->h_len += next_ptr->h_len;   /* first one gets second one's mem */
  1507. 18966         del_slot(hp, next_ptr);
  1508. 18967   } else {
  1509. 18968         hp = next_ptr;
  1510. 18969   }
  1511. 18970
  1512. 18971   /* If 'hp' now points to the last hole, return; otherwise, try to absorb its
  1513. 18972    * successor into it.
  1514. 18973    */
  1515. 18974   if ( (next_ptr = hp->h_next) == NIL_HOLE) return;
  1516. 18975   if (hp->h_base + hp->h_len == next_ptr->h_base) {
  1517. 18976         hp->h_len += next_ptr->h_len;
  1518. 18977         del_slot(hp, next_ptr);
  1519. 18978   }
  1520. 18979 }
  1521. 18982 /*===========================================================================*
  1522. 18983  *                              max_hole                                     *
  1523. 18984  *===========================================================================*/
  1524. 18985 PUBLIC phys_clicks max_hole()
  1525. 18986 {
  1526. 18987 /* Scan the hole list and return the largest hole. */
  1527. 18988
  1528. 18989   register struct hole *hp;
  1529. 18990   register phys_clicks max;
  1530. 18991
  1531. 18992   hp = hole_head;
  1532. 18993   max = 0;
  1533. 18994   while (hp != NIL_HOLE) {
  1534. 18995         if (hp->h_len > max) max = hp->h_len;
  1535. 18996         hp = hp->h_next;
  1536. 18997   }
  1537. 18998   return(max);
  1538. 18999 }
  1539. .Op 265 src/mm/alloc.c
  1540. 19002 /*===========================================================================*
  1541. 19003  *                              mem_init                                     *
  1542. 19004  *===========================================================================*/
  1543. 19005 PUBLIC void mem_init(total, free)
  1544. 19006 phys_clicks *total, *free;              /* memory size summaries */
  1545. 19007 {
  1546. 19008 /* Initialize hole lists.  There are two lists: 'hole_head' points to a linked
  1547. 19009  * list of all the holes (unused memory) in the system; 'free_slots' points to
  1548. 19010  * a linked list of table entries that are not in use.  Initially, the former
  1549. 19011  * list has one entry for each chunk of physical memory, and the second
  1550. 19012  * list links together the remaining table slots.  As memory becomes more
  1551. 19013  * fragmented in the course of time (i.e., the initial big holes break up into
  1552. 19014  * smaller holes), new table slots are needed to represent them.  These slots
  1553. 19015  * are taken from the list headed by 'free_slots'.
  1554. 19016  */
  1555. 19017
  1556. 19018   register struct hole *hp;
  1557. 19019   phys_clicks base;             /* base address of chunk */
  1558. 19020   phys_clicks size;             /* size of chunk */
  1559. 19021   message mess;
  1560. 19022
  1561. 19023   /* Put all holes on the free list. */
  1562. 19024   for (hp = &hole[0]; hp < &hole[NR_HOLES]; hp++) hp->h_next = hp + 1;
  1563. 19025   hole[NR_HOLES-1].h_next = NIL_HOLE;
  1564. 19026   hole_head = NIL_HOLE;
  1565. 19027   free_slots = &hole[0];
  1566. 19028
  1567. 19029   /* Ask the kernel for chunks of physical memory and allocate a hole for
  1568. 19030    * each of them.  The SYS_MEM call responds with the base and size of the
  1569. 19031    * next chunk and the total amount of memory.
  1570. 19032    */
  1571. 19033   *free = 0;
  1572. 19034   for (;;) {
  1573. 19035         mess.m_type = SYS_MEM;
  1574. 19036         if (sendrec(SYSTASK, &mess) != OK) panic("bad SYS_MEM?", NO_NUM);
  1575. 19037         base = mess.m1_i1;
  1576. 19038         size = mess.m1_i2;
  1577. 19039         if (size == 0) break;           /* no more? */
  1578. 19040
  1579. 19041         free_mem(base, size);
  1580. 19042         *total = mess.m1_i3;
  1581. 19043         *free += size;
  1582. 19044   }
  1583. 19045 }
  1584. .Ep 266 src/mm/utility.c
  1585. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1586. src/mm/utility.c    
  1587. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1588. 19100 /* This file contains some utility routines for MM.
  1589. 19101  *
  1590. 19102  * The entry points are:
  1591. 19103  *   allowed:   see if an access is permitted
  1592. 19104  *   no_sys:    this routine is called for invalid system call numbers
  1593. 19105  *   panic:     MM has run aground of a fatal error and cannot continue
  1594. 19106  *   tell_fs:   interface to FS
  1595. 19107  */
  1596. 19108
  1597. 19109 #include "mm.h"
  1598. 19110 #include <sys/stat.h>
  1599. 19111 #include <minix/callnr.h>
  1600. 19112 #include <minix/com.h>
  1601. 19113 #include <fcntl.h>
  1602. 19114 #include <signal.h>             /* needed only because mproc.h needs it */
  1603. 19115 #include "mproc.h"
  1604. 19116
  1605. 19117 /*===========================================================================*
  1606. 19118  *                              allowed                                      *
  1607. 19119  *===========================================================================*/
  1608. 19120 PUBLIC int allowed(name_buf, s_buf, mask)
  1609. 19121 char *name_buf;                 /* pointer to file name to be EXECed */
  1610. 19122 struct stat *s_buf;             /* buffer for doing and returning stat struct*/
  1611. 19123 int mask;                       /* R_BIT, W_BIT, or X_BIT */
  1612. 19124 {
  1613. 19125 /* Check to see if file can be accessed.  Return EACCES or ENOENT if the access
  1614. 19126  * is prohibited.  If it is legal open the file and return a file descriptor.
  1615. 19127  */
  1616. 19128
  1617. 19129   int fd;
  1618. 19130   int save_errno;
  1619. 19131
  1620. 19132   /* Use the fact that mask for access() is the same as the permissions mask.
  1621. 19133    * E.g., X_BIT in <minix/const.h> is the same as X_OK in <unistd.h> and
  1622. 19134    * S_IXOTH in <sys/stat.h>.  tell_fs(DO_CHDIR, ...) has set MM's real ids
  1623. 19135    * to the user's effective ids, so access() works right for setuid programs.
  1624. 19136    */
  1625. 19137   if (access(name_buf, mask) < 0) return(-errno);
  1626. 19138
  1627. 19139   /* The file is accessible but might not be readable.  Make it readable. */
  1628. 19140   tell_fs(SETUID, MM_PROC_NR, (int) SUPER_USER, (int) SUPER_USER);
  1629. 19141
  1630. 19142   /* Open the file and fstat it.  Restore the ids early to handle errors. */
  1631. 19143   fd = open(name_buf, O_RDONLY);
  1632. 19144   save_errno = errno;           /* open might fail, e.g. from ENFILE */
  1633. 19145   tell_fs(SETUID, MM_PROC_NR, (int) mp->mp_effuid, (int) mp->mp_effuid);
  1634. 19146   if (fd < 0) return(-save_errno);
  1635. 19147   if (fstat(fd, s_buf) < 0) panic("allowed: fstat failed", NO_NUM);
  1636. 19148
  1637. 19149   /* Only regular files can be executed. */
  1638. 19150   if (mask == X_BIT && (s_buf->st_mode & I_TYPE) != I_REGULAR) {
  1639. 19151         close(fd);
  1640. 19152         return(EACCES);
  1641. 19153   }
  1642. 19154   return(fd);
  1643. .Op 267 src/mm/utility.c
  1644. 19155 }
  1645. 19158 /*===========================================================================*
  1646. 19159  *                              no_sys                                       *
  1647. 19160  *===========================================================================*/
  1648. 19161 PUBLIC int no_sys()
  1649. 19162 {
  1650. 19163 /* A system call number not implemented by MM has been requested. */
  1651. 19164
  1652. 19165   return(EINVAL);
  1653. 19166 }
  1654. 19169 /*===========================================================================*
  1655. 19170  *                              panic                                        *
  1656. 19171  *===========================================================================*/
  1657. 19172 PUBLIC void panic(format, num)
  1658. 19173 char *format;                   /* format string */
  1659. 19174 int num;                        /* number to go with format string */
  1660. 19175 {
  1661. 19176 /* Something awful has happened.  Panics are caused when an internal
  1662. 19177  * inconsistency is detected, e.g., a programming error or illegal value of a
  1663. 19178  * defined constant.
  1664. 19179  */
  1665. 19180
  1666. 19181   printf("Memory manager panic: %s ", format);
  1667. 19182   if (num != NO_NUM) printf("%d",num);
  1668. 19183   printf("n");
  1669. 19184   tell_fs(SYNC, 0, 0, 0);       /* flush the cache to the disk */
  1670. 19185   sys_abort(RBT_PANIC);
  1671. 19186 }
  1672. 19189 /*===========================================================================*
  1673. 19190  *                              tell_fs                                      *
  1674. 19191  *===========================================================================*/
  1675. 19192 PUBLIC void tell_fs(what, p1, p2, p3)
  1676. 19193 int what, p1, p2, p3;
  1677. 19194 {
  1678. 19195 /* This routine is only used by MM to inform FS of certain events:
  1679. 19196  *      tell_fs(CHDIR, slot, dir, 0)
  1680. 19197  *      tell_fs(EXEC, proc, 0, 0)
  1681. 19198  *      tell_fs(EXIT, proc, 0, 0)
  1682. 19199  *      tell_fs(FORK, parent, child, pid)
  1683. 19200  *      tell_fs(SETGID, proc, realgid, effgid)
  1684. 19201  *      tell_fs(SETSID, proc, 0, 0)
  1685. 19202  *      tell_fs(SETUID, proc, realuid, effuid)
  1686. 19203  *      tell_fs(SYNC, 0, 0, 0)
  1687. 19204  *      tell_fs(UNPAUSE, proc, signr, 0)
  1688. 19205  */
  1689. 19206
  1690. 19207   message m;
  1691. 19208
  1692. 19209   m.m1_i1 = p1;
  1693. 19210   m.m1_i2 = p2;
  1694. 19211   m.m1_i3 = p3;
  1695. 19212   _taskcall(FS_PROC_NR, what, &m);
  1696. 19213 }
  1697. .Ep 268 src/mm/putk.c
  1698. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1699. src/mm/putk.c    
  1700. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1701. 19300 /* MM must occasionally print some message.  It uses the standard library
  1702. 19301  * routine printk().  (The name "printf" is really a macro defined as 
  1703. 19302  * "printk"). Printing is done by calling the TTY task directly, not going 
  1704. 19303  * through FS.
  1705. 19304  */
  1706. 19305
  1707. 19306 #include "mm.h"
  1708. 19307 #include <minix/com.h>
  1709. 19308
  1710. 19309 #define BUF_SIZE          100   /* print buffer size */
  1711. 19310
  1712. 19311 PRIVATE int buf_count;          /* # characters in the buffer */
  1713. 19312 PRIVATE char print_buf[BUF_SIZE];       /* output is buffered here */
  1714. 19313 PRIVATE message putch_msg;      /* used for message to TTY task */
  1715. 19314
  1716. 19315 _PROTOTYPE( FORWARD void flush, (void) );
  1717. 19316
  1718. 19317 /*===========================================================================*
  1719. 19318  *                              putk                                         *
  1720. 19319  *===========================================================================*/
  1721. 19320 PUBLIC void putk(c)
  1722. 19321 int c;
  1723. 19322 {
  1724. 19323 /* Accumulate another character.  If 0 or buffer full, print it. */
  1725. 19324
  1726. 19325   if (c == 0 || buf_count == BUF_SIZE) flush();
  1727. 19326   if (c == 'n') putk('r');
  1728. 19327   if (c != 0) print_buf[buf_count++] = c;
  1729. 19328 }
  1730. 19331 /*===========================================================================*
  1731. 19332  *                              flush                                        *
  1732. 19333  *===========================================================================*/
  1733. 19334 PRIVATE void flush()
  1734. 19335 {
  1735. 19336 /* Flush the print buffer by calling TTY task. */
  1736. 19337
  1737. 19338   if (buf_count == 0) return;
  1738. 19339   putch_msg.m_type = DEV_WRITE;
  1739. 19340   putch_msg.PROC_NR  = 0;
  1740. 19341   putch_msg.TTY_LINE = 0;
  1741. 19342   putch_msg.ADDRESS  = print_buf;
  1742. 19343   putch_msg.COUNT = buf_count;
  1743. 19344   sendrec(TTY, &putch_msg);
  1744. 19345   buf_count = 0;
  1745. 19346 }
  1746. .Op 269 src/fs/fs.h
  1747. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1748. src/fs/fs.h    
  1749. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1750. 19400 /* This is the master header for fs.  It includes some other files
  1751. 19401  * and defines the principal constants.
  1752. 19402  */
  1753. 19403 #define _POSIX_SOURCE      1    /* tell headers to include POSIX stuff */
  1754. 19404 #define _MINIX             1    /* tell headers to include MINIX stuff */
  1755. 19405 #define _SYSTEM            1    /* tell headers that this is the kernel */
  1756. 19406
  1757. 19407 /* The following are so basic, all the *.c files get them automatically. */
  1758. 19408 #include <minix/config.h>       /* MUST be first */
  1759. 19409 #include <ansi.h>               /* MUST be second */
  1760. 19410 #include <sys/types.h>
  1761. 19411 #include <minix/const.h>
  1762. 19412 #include <minix/type.h>
  1763. 19413
  1764. 19414 #include <limits.h>
  1765. 19415 #include <errno.h>
  1766. 19416
  1767. 19417 #include <minix/syslib.h>
  1768. 19418
  1769. 19419 #include "const.h"
  1770. 19420 #include "type.h"
  1771. 19421 #include "proto.h"
  1772. 19422 #include "glo.h"
  1773. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1774. src/fs/const.h    
  1775. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1776. 19500 /* Tables sizes */
  1777. 19501 #define V1_NR_DZONES       7    /* # direct zone numbers in a V1 inode */
  1778. 19502 #define V1_NR_TZONES       9    /* total # zone numbers in a V1 inode */
  1779. 19503 #define V2_NR_DZONES       7    /* # direct zone numbers in a V2 inode */
  1780. 19504 #define V2_NR_TZONES      10    /* total # zone numbers in a V2 inode */
  1781. 19505
  1782. 19506 #define NR_FILPS         128    /* # slots in filp table */
  1783. 19507 #define NR_INODES         64    /* # slots in "in core" inode table */
  1784. 19508 #define NR_SUPERS          8    /* # slots in super block table */
  1785. 19509 #define NR_LOCKS           8    /* # slots in the file locking table */
  1786. 19510
  1787. 19511 /* The type of sizeof may be (unsigned) long.  Use the following macro for
  1788. 19512  * taking the sizes of small objects so that there are no surprises like
  1789. 19513  * (small) long constants being passed to routines expecting an int.
  1790. 19514  */
  1791. 19515 #define usizeof(t) ((unsigned) sizeof(t))
  1792. 19516
  1793. 19517 /* File system types. */
  1794. 19518 #define SUPER_MAGIC   0x137F    /* magic number contained in super-block */
  1795. 19519 #define SUPER_REV     0x7F13    /* magic # when 68000 disk read on PC or vv */
  1796. 19520 #define SUPER_V2      0x2468    /* magic # for V2 file systems */
  1797. 19521 #define SUPER_V2_REV  0x6824    /* V2 magic written on PC, read on 68K or vv */
  1798. 19522
  1799. 19523 #define V1                 1    /* version number of V1 file systems */ 
  1800. 19524 #define V2                 2    /* version number of V2 file systems */ 
  1801. .Ep 270 src/fs/const.h
  1802. 19525
  1803. 19526 /* Miscellaneous constants */
  1804. 19527 #define SU_UID   ((uid_t) 0)    /* super_user's uid_t */
  1805. 19528 #define SYS_UID  ((uid_t) 0)    /* uid_t for processes MM and INIT */
  1806. 19529 #define SYS_GID  ((gid_t) 0)    /* gid_t for processes MM and INIT */
  1807. 19530 #define NORMAL             0    /* forces get_block to do disk read */
  1808. 19531 #define NO_READ            1    /* prevents get_block from doing disk read */
  1809. 19532 #define PREFETCH           2    /* tells get_block not to read or mark dev */
  1810. 19533
  1811. 19534 #define XPIPE  (-NR_TASKS-1)    /* used in fp_task when susp'd on pipe */
  1812. 19535 #define XOPEN  (-NR_TASKS-2)    /* used in fp_task when susp'd on open */
  1813. 19536 #define XLOCK  (-NR_TASKS-3)    /* used in fp_task when susp'd on lock */
  1814. 19537 #define XPOPEN (-NR_TASKS-4)    /* used in fp_task when susp'd on pipe open */
  1815. 19538
  1816. 19539 #define NO_BIT   ((bit_t) 0)    /* returned by alloc_bit() to signal failure */
  1817. 19540
  1818. 19541 #define DUP_MASK        0100    /* mask to distinguish dup2 from dup */
  1819. 19542
  1820. 19543 #define LOOK_UP            0    /* tells search_dir to lookup string */
  1821. 19544 #define ENTER              1    /* tells search_dir to make dir entry */
  1822. 19545 #define DELETE             2    /* tells search_dir to delete entry */
  1823. 19546 #define IS_EMPTY           3    /* tells search_dir to ret. OK or ENOTEMPTY */  
  1824. 19547
  1825. 19548 #define CLEAN              0    /* disk and memory copies identical */
  1826. 19549 #define DIRTY              1    /* disk and memory copies differ */
  1827. 19550 #define ATIME            002    /* set if atime field needs updating */
  1828. 19551 #define CTIME            004    /* set if ctime field needs updating */
  1829. 19552 #define MTIME            010    /* set if mtime field needs updating */
  1830. 19553
  1831. 19554 #define BYTE_SWAP          0    /* tells conv2/conv4 to swap bytes */
  1832. 19555 #define DONT_SWAP          1    /* tells conv2/conv4 not to swap bytes */
  1833. 19556
  1834. 19557 #define END_OF_FILE   (-104)    /* eof detected */
  1835. 19558
  1836. 19559 #define ROOT_INODE         1    /* inode number for root directory */
  1837. 19560 #define BOOT_BLOCK  ((block_t) 0)       /* block number of boot block */
  1838. 19561 #define SUPER_BLOCK ((block_t) 1)       /* block number of super block */
  1839. 19562
  1840. 19563 #define DIR_ENTRY_SIZE       usizeof (struct direct)  /* # bytes/dir entry   */
  1841. 19564 #define NR_DIR_ENTRIES   (BLOCK_SIZE/DIR_ENTRY_SIZE)  /* # dir entries/blk   */
  1842. 19565 #define SUPER_SIZE      usizeof (struct super_block)  /* super_block size    */
  1843. 19566 #define PIPE_SIZE          (V1_NR_DZONES*BLOCK_SIZE)  /* pipe size in bytes  */
  1844. 19567 #define BITMAP_CHUNKS (BLOCK_SIZE/usizeof (bitchunk_t))/* # map chunks/blk   */
  1845. 19568
  1846. 19569 /* Derived sizes pertaining to the V1 file system. */
  1847. 19570 #define V1_ZONE_NUM_SIZE           usizeof (zone1_t)  /* # bytes in V1 zone  */
  1848. 19571 #define V1_INODE_SIZE             usizeof (d1_inode)  /* bytes in V1 dsk ino */
  1849. 19572 #define V1_INDIRECTS   (BLOCK_SIZE/V1_ZONE_NUM_SIZE)  /* # zones/indir block */
  1850. 19573 #define V1_INODES_PER_BLOCK (BLOCK_SIZE/V1_INODE_SIZE)/* # V1 dsk inodes/blk */
  1851. 19574
  1852. 19575 /* Derived sizes pertaining to the V2 file system. */
  1853. 19576 #define V2_ZONE_NUM_SIZE            usizeof (zone_t)  /* # bytes in V2 zone  */
  1854. 19577 #define V2_INODE_SIZE             usizeof (d2_inode)  /* bytes in V2 dsk ino */
  1855. 19578 #define V2_INDIRECTS   (BLOCK_SIZE/V2_ZONE_NUM_SIZE)  /* # zones/indir block */
  1856. 19579 #define V2_INODES_PER_BLOCK (BLOCK_SIZE/V2_INODE_SIZE)/* # V2 dsk inodes/blk */
  1857. 19580
  1858. 19581 #define printf printk
  1859. .Op 271 src/fs/type.h
  1860. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1861. src/fs/type.h    
  1862. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1863. 19600 /* Declaration of the V1 inode as it is on the disk (not in core). */
  1864. 19601 typedef struct {                /* V1.x disk inode */
  1865. 19602   mode_t d1_mode;               /* file type, protection, etc. */
  1866. 19603   uid_t d1_uid;                 /* user id of the file's owner */
  1867. 19604   off_t d1_size;                /* current file size in bytes */
  1868. 19605   time_t d1_mtime;              /* when was file data last changed */
  1869. 19606   gid_t d1_gid;                 /* group number */
  1870. 19607   nlink_t d1_nlinks;            /* how many links to this file */
  1871. 19608   u16_t d1_zone[V1_NR_TZONES];  /* block nums for direct, ind, and dbl ind */
  1872. 19609 } d1_inode;
  1873. 19610
  1874. 19611 /* Declaration of the V2 inode as it is on the disk (not in core). */
  1875. 19612 typedef struct {                /* V2.x disk inode */
  1876. 19613   mode_t d2_mode;               /* file type, protection, etc. */
  1877. 19614   u16_t d2_nlinks;              /* how many links to this file. HACK! */
  1878. 19615   uid_t d2_uid;                 /* user id of the file's owner. */
  1879. 19616   u16_t d2_gid;                 /* group number HACK! */
  1880. 19617   off_t d2_size;                /* current file size in bytes */
  1881. 19618   time_t d2_atime;              /* when was file data last accessed */
  1882. 19619   time_t d2_mtime;              /* when was file data last changed */
  1883. 19620   time_t d2_ctime;              /* when was inode data last changed */
  1884. 19621   zone_t d2_zone[V2_NR_TZONES]; /* block nums for direct, ind, and dbl ind */
  1885. 19622 } d2_inode;
  1886. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1887. src/fs/proto.h    
  1888. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1889. 19700 /* Function prototypes. */
  1890. 19701
  1891. 19702 /* Structs used in prototypes must be declared as such first. */
  1892. 19703 struct buf;
  1893. 19704 struct filp;            
  1894. 19705 struct inode;
  1895. 19706 struct super_block;
  1896. 19707
  1897. 19708 /* cache.c */
  1898. 19709 _PROTOTYPE( zone_t alloc_zone, (Dev_t dev, zone_t z)                    );
  1899. 19710 _PROTOTYPE( void flushall, (Dev_t dev)                                  );
  1900. 19711 _PROTOTYPE( void free_zone, (Dev_t dev, zone_t numb)                    );
  1901. 19712 _PROTOTYPE( struct buf *get_block, (Dev_t dev, block_t block,int only_search));
  1902. 19713 _PROTOTYPE( void invalidate, (Dev_t device)                             );
  1903. 19714 _PROTOTYPE( void put_block, (struct buf *bp, int block_type)            );
  1904. 19715 _PROTOTYPE( void rw_block, (struct buf *bp, int rw_flag)                );
  1905. 19716 _PROTOTYPE( void rw_scattered, (Dev_t dev,
  1906. 19717                         struct buf **bufq, int bufqsize, int rw_flag)   );
  1907. 19718
  1908. 19719 /* device.c */
  1909. 19720 _PROTOTYPE( void call_task, (int task_nr, message *mess_ptr)            );
  1910. 19721 _PROTOTYPE( void dev_opcl, (int task_nr, message *mess_ptr)             );
  1911. 19722 _PROTOTYPE( int dev_io, (int rw_flag, int nonblock, Dev_t dev,
  1912. 19723                         off_t pos, int bytes, int proc, char *buff)     );
  1913. 19724 _PROTOTYPE( int do_ioctl, (void)                                        );
  1914. .Ep 272 src/fs/proto.h
  1915. 19725 _PROTOTYPE( void no_dev, (int task_nr, message *m_ptr)                  );
  1916. 19726 _PROTOTYPE( void call_ctty, (int task_nr, message *mess_ptr)            );
  1917. 19727 _PROTOTYPE( void tty_open, (int task_nr, message *mess_ptr)             );
  1918. 19728 _PROTOTYPE( void ctty_close, (int task_nr, message *mess_ptr)           );
  1919. 19729 _PROTOTYPE( void ctty_open, (int task_nr, message *mess_ptr)            );
  1920. 19730 _PROTOTYPE( int do_setsid, (void)                                       );
  1921. 19731 #if ENABLE_NETWORKING
  1922. 19732 _PROTOTYPE( void net_open, (int task_nr, message *mess_ptr)             );
  1923. 19733 #else
  1924. 19734 #define net_open  0
  1925. 19735 #endif
  1926. 19736
  1927. 19737 /* filedes.c */
  1928. 19738 _PROTOTYPE( struct filp *find_filp, (struct inode *rip, Mode_t bits)    );
  1929. 19739 _PROTOTYPE( int get_fd, (int start, Mode_t bits, int *k, struct filp **fpt) );
  1930. 19740 _PROTOTYPE( struct filp *get_filp, (int fild)                           );
  1931. 19741
  1932. 19742 /* inode.c */
  1933. 19743 _PROTOTYPE( struct inode *alloc_inode, (Dev_t dev, Mode_t bits)         );
  1934. 19744 _PROTOTYPE( void dup_inode, (struct inode *ip)                          );
  1935. 19745 _PROTOTYPE( void free_inode, (Dev_t dev, Ino_t numb)                    );
  1936. 19746 _PROTOTYPE( struct inode *get_inode, (Dev_t dev, int numb)              );
  1937. 19747 _PROTOTYPE( void put_inode, (struct inode *rip)                         );
  1938. 19748 _PROTOTYPE( void update_times, (struct inode *rip)                      );
  1939. 19749 _PROTOTYPE( void rw_inode, (struct inode *rip, int rw_flag)             );
  1940. 19750 _PROTOTYPE( void wipe_inode, (struct inode *rip)                        );
  1941. 19751
  1942. 19752 /* link.c */
  1943. 19753 _PROTOTYPE( int do_link, (void)                                         );
  1944. 19754 _PROTOTYPE( int do_unlink, (void)                                       );
  1945. 19755 _PROTOTYPE( int do_rename, (void)                                       );
  1946. 19756 _PROTOTYPE( void truncate, (struct inode *rip)                          );
  1947. 19757
  1948. 19758 /* lock.c */
  1949. 19759 _PROTOTYPE( int lock_op, (struct filp *f, int req)                      );
  1950. 19760 _PROTOTYPE( void lock_revive, (void)                                    );
  1951. 19761
  1952. 19762 /* main.c */
  1953. 19763 _PROTOTYPE( void main, (void)                                           );
  1954. 19764 _PROTOTYPE( void reply, (int whom, int result)                          );
  1955. 19765
  1956. 19766 /* misc.c */
  1957. 19767 _PROTOTYPE( int do_dup, (void)                                          );
  1958. 19768 _PROTOTYPE( int do_exit, (void)                                         );
  1959. 19769 _PROTOTYPE( int do_fcntl, (void)                                        );
  1960. 19770 _PROTOTYPE( int do_fork, (void)                                         );
  1961. 19771 _PROTOTYPE( int do_exec, (void)                                         );
  1962. 19772 _PROTOTYPE( int do_revive, (void)                                       );
  1963. 19773 _PROTOTYPE( int do_set, (void)                                          );
  1964. 19774 _PROTOTYPE( int do_sync, (void)                                         );
  1965. 19775
  1966. 19776 /* mount.c */
  1967. 19777 _PROTOTYPE( int do_mount, (void)                                        );
  1968. 19778 _PROTOTYPE( int do_umount, (void)                                       );
  1969. 19779
  1970. 19780 /* open.c */
  1971. 19781 _PROTOTYPE( int do_close, (void)                                        );
  1972. 19782 _PROTOTYPE( int do_creat, (void)                                        );
  1973. 19783 _PROTOTYPE( int do_lseek, (void)                                        );
  1974. 19784 _PROTOTYPE( int do_mknod, (void)                                        );
  1975. .Op 273 src/fs/proto.h
  1976. 19785 _PROTOTYPE( int do_mkdir, (void)                                        );
  1977. 19786 _PROTOTYPE( int do_open, (void)                                         );
  1978. 19787
  1979. 19788 /* path.c */
  1980. 19789 _PROTOTYPE( struct inode *advance,(struct inode *dirp, char string[NAME_MAX]));
  1981. 19790 _PROTOTYPE( int search_dir, (struct inode *ldir_ptr,
  1982. 19791                         char string [NAME_MAX], ino_t *numb, int flag)  );
  1983. 19792 _PROTOTYPE( struct inode *eat_path, (char *path)                        );
  1984. 19793 _PROTOTYPE( struct inode *last_dir, (char *path, char string [NAME_MAX]));
  1985. 19794
  1986. 19795 /* pipe.c */
  1987. 19796 _PROTOTYPE( int do_pipe, (void)                                         );
  1988. 19797 _PROTOTYPE( int do_unpause, (void)                                      );
  1989. 19798 _PROTOTYPE( int pipe_check, (struct inode *rip, int rw_flag,
  1990. 19799                         int oflags, int bytes, off_t position, int *canwrite));
  1991. 19800 _PROTOTYPE( void release, (struct inode *ip, int call_nr, int count)    );
  1992. 19801 _PROTOTYPE( void revive, (int proc_nr, int bytes)                       );
  1993. 19802 _PROTOTYPE( void suspend, (int task)                                    );
  1994. 19803
  1995. 19804 /* protect.c */
  1996. 19805 _PROTOTYPE( int do_access, (void)                                       );
  1997. 19806 _PROTOTYPE( int do_chmod, (void)                                        );
  1998. 19807 _PROTOTYPE( int do_chown, (void)                                        );
  1999. 19808 _PROTOTYPE( int do_umask, (void)                                        );
  2000. 19809 _PROTOTYPE( int forbidden, (struct inode *rip, Mode_t access_desired)   );
  2001. 19810 _PROTOTYPE( int read_only, (struct inode *ip)                           );
  2002. 19811
  2003. 19812 /* putk.c */
  2004. 19813 _PROTOTYPE( void putk, (int c)                                          );
  2005. 19814
  2006. 19815 /* read.c */
  2007. 19816 _PROTOTYPE( int do_read, (void)                                         );
  2008. 19817 _PROTOTYPE( struct buf *rahead, (struct inode *rip, block_t baseblock,
  2009. 19818                         off_t position, unsigned bytes_ahead)           );
  2010. 19819 _PROTOTYPE( void read_ahead, (void)                                     );
  2011. 19820 _PROTOTYPE( block_t read_map, (struct inode *rip, off_t position)       );
  2012. 19821 _PROTOTYPE( int read_write, (int rw_flag)                               );
  2013. 19822 _PROTOTYPE( zone_t rd_indir, (struct buf *bp, int index)                );
  2014. 19823
  2015. 19824 /* stadir.c */
  2016. 19825 _PROTOTYPE( int do_chdir, (void)                                        );
  2017. 19826 _PROTOTYPE( int do_chroot, (void)                                       );
  2018. 19827 _PROTOTYPE( int do_fstat, (void)                                        );
  2019. 19828 _PROTOTYPE( int do_stat, (void)                                         );
  2020. 19829
  2021. 19830 /* super.c */
  2022. 19831 _PROTOTYPE( bit_t alloc_bit, (struct super_block *sp, int map, bit_t origin));
  2023. 19832 _PROTOTYPE( void free_bit, (struct super_block *sp, int map,
  2024. 19833                                                 bit_t bit_returned)     );
  2025. 19834 _PROTOTYPE( struct super_block *get_super, (Dev_t dev)                  );
  2026. 19835 _PROTOTYPE( int mounted, (struct inode *rip)                            );
  2027. 19836 _PROTOTYPE( int read_super, (struct super_block *sp)                    );
  2028. 19837
  2029. 19838 /* time.c */
  2030. 19839 _PROTOTYPE( int do_stime, (void)                                        );
  2031. 19840 _PROTOTYPE( int do_time, (void)                                         );
  2032. 19841 _PROTOTYPE( int do_tims, (void)                                         );
  2033. 19842 _PROTOTYPE( int do_utime, (void)                                        );
  2034. 19843
  2035. 19844 /* utility.c */
  2036. .Ep 274 src/fs/proto.h
  2037. 19845 _PROTOTYPE( time_t clock_time, (void)                                   );
  2038. 19846 _PROTOTYPE( unsigned conv2, (int norm, int w)                           );
  2039. 19847 _PROTOTYPE( long conv4, (int norm, long x)                              );
  2040. 19848 _PROTOTYPE( int fetch_name, (char *path, int len, int flag)             );
  2041. 19849 _PROTOTYPE( int no_sys, (void)                                          );
  2042. 19850 _PROTOTYPE( void panic, (char *format, int num)                         );
  2043. 19851
  2044. 19852 /* write.c */
  2045. 19853 _PROTOTYPE( void clear_zone, (struct inode *rip, off_t pos, int flag)   );
  2046. 19854 _PROTOTYPE( int do_write, (void)                                        );
  2047. 19855 _PROTOTYPE( struct buf *new_block, (struct inode *rip, off_t position)  );
  2048. 19856 _PROTOTYPE( void zero_block, (struct buf *bp)                           );
  2049. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2050. src/fs/glo.h    
  2051. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2052. 19900 /* EXTERN should be extern except for the table file */
  2053. 19901 #ifdef _TABLE
  2054. 19902 #undef EXTERN
  2055. 19903 #define EXTERN
  2056. 19904 #endif
  2057. 19905
  2058. 19906 /* File System global variables */
  2059. 19907 EXTERN struct fproc *fp;        /* pointer to caller's fproc struct */
  2060. 19908 EXTERN int super_user;          /* 1 if caller is super_user, else 0 */
  2061. 19909 EXTERN int dont_reply;          /* normally 0; set to 1 to inhibit reply */
  2062. 19910 EXTERN int susp_count;          /* number of procs suspended on pipe */
  2063. 19911 EXTERN int nr_locks;            /* number of locks currently in place */
  2064. 19912 EXTERN int reviving;            /* number of pipe processes to be revived */
  2065. 19913 EXTERN off_t rdahedpos;         /* position to read ahead */
  2066. 19914 EXTERN struct inode *rdahed_inode;      /* pointer to inode to read ahead */
  2067. 19915
  2068. 19916 /* The parameters of the call are kept here. */
  2069. 19917 EXTERN message m;               /* the input message itself */
  2070. 19918 EXTERN message m1;              /* the output message used for reply */
  2071. 19919 EXTERN int who;                 /* caller's proc number */
  2072. 19920 EXTERN int fs_call;             /* system call number */
  2073. 19921 EXTERN char user_path[PATH_MAX];/* storage for user path name */
  2074. 19922
  2075. 19923 /* The following variables are used for returning results to the caller. */
  2076. 19924 EXTERN int err_code;            /* temporary storage for error number */
  2077. 19925 EXTERN int rdwt_err;            /* status of last disk i/o request */
  2078. 19926
  2079. 19927 /* Data which need initialization. */
  2080. 19928 extern _PROTOTYPE (int (*call_vector[]), (void) ); /* sys call table */
  2081. 19929 extern int max_major;  /* maximum major device (+ 1) */
  2082. 19930 extern char dot1[2];   /* dot1 (&dot1[0]) and dot2 (&dot2[0]) have a special */
  2083. 19931 extern char dot2[3];   /* meaning to search_dir: no access permission check. */
  2084. .Op 275 src/fs/fproc.h
  2085. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2086. src/fs/fproc.h    
  2087. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2088. 20000 /* This is the per-process information.  A slot is reserved for each potential
  2089. 20001  * process. Thus NR_PROCS must be the same as in the kernel. It is not possible
  2090. 20002  * or even necessary to tell when a slot is free here.
  2091. 20003  */
  2092. 20004
  2093. 20005
  2094. 20006 EXTERN struct fproc {
  2095. 20007   mode_t fp_umask;              /* mask set by umask system call */
  2096. 20008   struct inode *fp_workdir;     /* pointer to working directory's inode */
  2097. 20009   struct inode *fp_rootdir;     /* pointer to current root dir (see chroot) */
  2098. 20010   struct filp *fp_filp[OPEN_MAX];/* the file descriptor table */
  2099. 20011   uid_t fp_realuid;             /* real user id */
  2100. 20012   uid_t fp_effuid;              /* effective user id */
  2101. 20013   gid_t fp_realgid;             /* real group id */
  2102. 20014   gid_t fp_effgid;              /* effective group id */
  2103. 20015   dev_t fp_tty;                 /* major/minor of controlling tty */
  2104. 20016   int fp_fd;                    /* place to save fd if rd/wr can't finish */
  2105. 20017   char *fp_buffer;              /* place to save buffer if rd/wr can't finish*/
  2106. 20018   int  fp_nbytes;               /* place to save bytes if rd/wr can't finish */
  2107. 20019   int  fp_cum_io_partial;       /* partial byte count if rd/wr can't finish */
  2108. 20020   char fp_suspended;            /* set to indicate process hanging */
  2109. 20021   char fp_revived;              /* set to indicate process being revived */
  2110. 20022   char fp_task;                 /* which task is proc suspended on */
  2111. 20023   char fp_sesldr;               /* true if proc is a session leader */
  2112. 20024   pid_t fp_pid;                 /* process id */
  2113. 20025   long fp_cloexec;              /* bit map for POSIX Table 6-2 FD_CLOEXEC */
  2114. 20026 } fproc[NR_PROCS];
  2115. 20027
  2116. 20028 /* Field values. */
  2117. 20029 #define NOT_SUSPENDED      0    /* process is not suspended on pipe or task */
  2118. 20030 #define SUSPENDED          1    /* process is suspended on pipe or task */
  2119. 20031 #define NOT_REVIVING       0    /* process is not being revived */
  2120. 20032 #define REVIVING           1    /* process is being revived from suspension */
  2121. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2122. src/fs/buf.h    
  2123. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2124. 20100 /* Buffer (block) cache.  To acquire a block, a routine calls get_block(),
  2125. 20101  * telling which block it wants.  The block is then regarded as "in use"
  2126. 20102  * and has its 'b_count' field incremented.  All the blocks that are not
  2127. 20103  * in use are chained together in an LRU list, with 'front' pointing
  2128. 20104  * to the least recently used block, and 'rear' to the most recently used
  2129. 20105  * block.  A reverse chain, using the field b_prev is also maintained.
  2130. 20106  * Usage for LRU is measured by the time the put_block() is done.  The second
  2131. 20107  * parameter to put_block() can violate the LRU order and put a block on the
  2132. 20108  * front of the list, if it will probably not be needed soon.  If a block
  2133. 20109  * is modified, the modifying routine must set b_dirt to DIRTY, so the block
  2134. 20110  * will eventually be rewritten to the disk.
  2135. 20111  */
  2136. 20112
  2137. 20113 #include <sys/dir.h>                    /* need struct direct */
  2138. 20114
  2139. .Ep 276 src/fs/buf.h
  2140. 20115 EXTERN struct buf {
  2141. 20116   /* Data portion of the buffer. */
  2142. 20117   union {
  2143. 20118     char b__data[BLOCK_SIZE];                /* ordinary user data */
  2144. 20119     struct direct b__dir[NR_DIR_ENTRIES];    /* directory block */
  2145. 20120     zone1_t b__v1_ind[V1_INDIRECTS];         /* V1 indirect block */
  2146. 20121     zone_t  b__v2_ind[V2_INDIRECTS];         /* V2 indirect block */
  2147. 20122     d1_inode b__v1_ino[V1_INODES_PER_BLOCK]; /* V1 inode block */
  2148. 20123     d2_inode b__v2_ino[V2_INODES_PER_BLOCK]; /* V2 inode block */
  2149. 20124     bitchunk_t b__bitmap[BITMAP_CHUNKS];     /* bit map block */
  2150. 20125   } b;
  2151. 20126
  2152. 20127   /* Header portion of the buffer. */
  2153. 20128   struct buf *b_next;           /* used to link all free bufs in a chain */
  2154. 20129   struct buf *b_prev;           /* used to link all free bufs the other way */
  2155. 20130   struct buf *b_hash;           /* used to link bufs on hash chains */
  2156. 20131   block_t b_blocknr;            /* block number of its (minor) device */
  2157. 20132   dev_t b_dev;                  /* major | minor device where block resides */
  2158. 20133   char b_dirt;                  /* CLEAN or DIRTY */
  2159. 20134   char b_count;                 /* number of users of this buffer */
  2160. 20135 } buf[NR_BUFS];
  2161. 20136
  2162. 20137 /* A block is free if b_dev == NO_DEV. */
  2163. 20138
  2164. 20139 #define NIL_BUF ((struct buf *) 0)      /* indicates absence of a buffer */
  2165. 20140
  2166. 20141 /* These defs make it possible to use to bp->b_data instead of bp->b.b__data */
  2167. 20142 #define b_data   b.b__data
  2168. 20143 #define b_dir    b.b__dir
  2169. 20144 #define b_v1_ind b.b__v1_ind
  2170. 20145 #define b_v2_ind b.b__v2_ind
  2171. 20146 #define b_v1_ino b.b__v1_ino
  2172. 20147 #define b_v2_ino b.b__v2_ino
  2173. 20148 #define b_bitmap b.b__bitmap
  2174. 20149
  2175. 20150 EXTERN struct buf *buf_hash[NR_BUF_HASH];       /* the buffer hash table */
  2176. 20151
  2177. 20152 EXTERN struct buf *front;       /* points to least recently used free block */
  2178. 20153 EXTERN struct buf *rear;        /* points to most recently used free block */
  2179. 20154 EXTERN int bufs_in_use;         /* # bufs currently in use (not on free list)*/
  2180. 20155
  2181. 20156 /* When a block is released, the type of usage is passed to put_block(). */
  2182. 20157 #define WRITE_IMMED        0100 /* block should be written to disk now */
  2183. 20158 #define ONE_SHOT           0200 /* set if block not likely to be needed soon */
  2184. 20159
  2185. 20160 #define INODE_BLOCK       (0 + MAYBE_WRITE_IMMED)        /* inode block */
  2186. 20161 #define DIRECTORY_BLOCK   (1 + MAYBE_WRITE_IMMED)        /* directory block */
  2187. 20162 #define INDIRECT_BLOCK    (2 + MAYBE_WRITE_IMMED)        /* pointer block */
  2188. 20163 #define MAP_BLOCK         (3 + MAYBE_WRITE_IMMED)        /* bit map */
  2189. 20164 #define ZUPER_BLOCK       (4 + WRITE_IMMED + ONE_SHOT)   /* super block */
  2190. 20165 #define FULL_DATA_BLOCK    5                             /* data, fully used */
  2191. 20166 #define PARTIAL_DATA_BLOCK 6                             /* data, partly used*/
  2192. 20167
  2193. 20168 #define HASH_MASK (NR_BUF_HASH - 1)     /* mask for hashing block numbers */
  2194. .Op 277 src/fs/dev.h
  2195. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2196. src/fs/dev.h    
  2197. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2198. 20200 /* Device table.  This table is indexed by major device number.  It provides
  2199. 20201  * the link between major device numbers and the routines that process them.
  2200. 20202  */
  2201. 20203
  2202. 20204 typedef _PROTOTYPE (void (*dmap_t), (int task, message *m_ptr) );
  2203. 20205
  2204. 20206 extern struct dmap {
  2205. 20207   dmap_t dmap_open;
  2206. 20208   dmap_t dmap_rw;
  2207. 20209   dmap_t dmap_close;
  2208. 20210   int dmap_task;
  2209. 20211 } dmap[];
  2210. 20212
  2211. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2212. src/fs/file.h    
  2213. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2214. 20300 /* This is the filp table.  It is an intermediary between file descriptors and
  2215. 20301  * inodes.  A slot is free if filp_count == 0.
  2216. 20302  */
  2217. 20303
  2218. 20304 EXTERN struct filp {
  2219. 20305   mode_t filp_mode;             /* RW bits, telling how file is opened */
  2220. 20306   int filp_flags;               /* flags from open and fcntl */
  2221. 20307   int filp_count;               /* how many file descriptors share this slot?*/
  2222. 20308   struct inode *filp_ino;       /* pointer to the inode */
  2223. 20309   off_t filp_pos;               /* file position */
  2224. 20310 } filp[NR_FILPS];
  2225. 20311
  2226. 20312 #define FILP_CLOSED     0       /* filp_mode: associated device closed */
  2227. 20313
  2228. 20314 #define NIL_FILP (struct filp *) 0      /* indicates absence of a filp slot */
  2229. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2230. src/fs/lock.h    
  2231. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2232. 20400 /* This is the file locking table.  Like the filp table, it points to the
  2233. 20401  * inode table, however, in this case to achieve advisory locking.
  2234. 20402  */
  2235. 20403 EXTERN struct file_lock {
  2236. 20404   short lock_type;              /* F_RDLOCK or F_WRLOCK; 0 means unused slot */
  2237. 20405   pid_t lock_pid;               /* pid of the process holding the lock */
  2238. 20406   struct inode *lock_inode;     /* pointer to the inode locked */
  2239. 20407   off_t lock_first;             /* offset of first byte locked */
  2240. 20408   off_t lock_last;              /* offset of last byte locked */
  2241. 20409 } file_lock[NR_LOCKS];
  2242. .Ep 278 src/fs/inode.h
  2243. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2244. src/fs/inode.h    
  2245. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2246. 20500 /* Inode table.  This table holds inodes that are currently in use.  In some
  2247. 20501  * cases they have been opened by an open() or creat() system call, in other
  2248. 20502  * cases the file system itself needs the inode for one reason or another,
  2249. 20503  * such as to search a directory for a path name.
  2250. 20504  * The first part of the struct holds fields that are present on the
  2251. 20505  * disk; the second part holds fields not present on the disk.
  2252. 20506  * The disk inode part is also declared in "type.h" as 'd1_inode' for V1
  2253. 20507  * file systems and 'd2_inode' for V2 file systems.
  2254. 20508  */
  2255. 20509
  2256. 20510 EXTERN struct inode {
  2257. 20511   mode_t i_mode;                /* file type, protection, etc. */
  2258. 20512   nlink_t i_nlinks;             /* how many links to this file */
  2259. 20513   uid_t i_uid;                  /* user id of the file's owner */
  2260. 20514   gid_t i_gid;                  /* group number */
  2261. 20515   off_t i_size;                 /* current file size in bytes */
  2262. 20516   time_t i_atime;               /* time of last access (V2 only) */
  2263. 20517   time_t i_mtime;               /* when was file data last changed */
  2264. 20518   time_t i_ctime;               /* when was inode itself changed (V2 only)*/
  2265. 20519   zone_t i_zone[V2_NR_TZONES];  /* zone numbers for direct, ind, and dbl ind */
  2266. 20520   
  2267. 20521   /* The following items are not present on the disk. */
  2268. 20522   dev_t i_dev;                  /* which device is the inode on */
  2269. 20523   ino_t i_num;                  /* inode number on its (minor) device */
  2270. 20524   int i_count;                  /* # times inode used; 0 means slot is free */
  2271. 20525   int i_ndzones;                /* # direct zones (Vx_NR_DZONES) */
  2272. 20526   int i_nindirs;                /* # indirect zones per indirect block */
  2273. 20527   struct super_block *i_sp;     /* pointer to super block for inode's device */
  2274. 20528   char i_dirt;                  /* CLEAN or DIRTY */
  2275. 20529   char i_pipe;                  /* set to I_PIPE if pipe */
  2276. 20530   char i_mount;                 /* this bit is set if file mounted on */
  2277. 20531   char i_seek;                  /* set on LSEEK, cleared on READ/WRITE */
  2278. 20532   char i_update;                /* the ATIME, CTIME, and MTIME bits are here */
  2279. 20533 } inode[NR_INODES];
  2280. 20534
  2281. 20535
  2282. 20536 #define NIL_INODE (struct inode *) 0    /* indicates absence of inode slot */
  2283. 20537
  2284. 20538 /* Field values.  Note that CLEAN and DIRTY are defined in "const.h" */
  2285. 20539 #define NO_PIPE            0    /* i_pipe is NO_PIPE if inode is not a pipe */
  2286. 20540 #define I_PIPE             1    /* i_pipe is I_PIPE if inode is a pipe */
  2287. 20541 #define NO_MOUNT           0    /* i_mount is NO_MOUNT if file not mounted on*/
  2288. 20542 #define I_MOUNT            1    /* i_mount is I_MOUNT if file mounted on */
  2289. 20543 #define NO_SEEK            0    /* i_seek = NO_SEEK if last op was not SEEK */
  2290. 20544 #define ISEEK              1    /* i_seek = ISEEK if last op was SEEK */
  2291. .Op 279 src/fs/param.h
  2292. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2293. src/fs/param.h    
  2294. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2295. 20600 /* The following names are synonyms for the variables in the input message. */
  2296. 20601 #define acc_time      m.m2_l1
  2297. 20602 #define addr          m.m1_i3
  2298. 20603 #define buffer        m.m1_p1
  2299. 20604 #define child         m.m1_i2
  2300. 20605 #define co_mode       m.m1_i1
  2301. 20606 #define eff_grp_id    m.m1_i3
  2302. 20607 #define eff_user_id   m.m1_i3
  2303. 20608 #define erki          m.m1_p1
  2304. 20609 #define fd            m.m1_i1
  2305. 20610 #define fd2           m.m1_i2
  2306. 20611 #define ioflags       m.m1_i3
  2307. 20612 #define group         m.m1_i3
  2308. 20613 #define real_grp_id   m.m1_i2
  2309. 20614 #define ls_fd         m.m2_i1
  2310. 20615 #define mk_mode       m.m1_i2
  2311. 20616 #define mode          m.m3_i2
  2312. 20617 #define c_mode        m.m1_i3
  2313. 20618 #define c_name        m.m1_p1
  2314. 20619 #define name          m.m3_p1
  2315. 20620 #define name1         m.m1_p1
  2316. 20621 #define name2         m.m1_p2
  2317. 20622 #define name_length   m.m3_i1
  2318. 20623 #define name1_length  m.m1_i1
  2319. 20624 #define name2_length  m.m1_i2
  2320. 20625 #define nbytes        m.m1_i2
  2321. 20626 #define offset        m.m2_l1
  2322. 20627 #define owner         m.m1_i2
  2323. 20628 #define parent        m.m1_i1
  2324. 20629 #define pathname      m.m3_ca1
  2325. 20630 #define pid           m.m1_i3
  2326. 20631 #define pro           m.m1_i1
  2327. 20632 #define rd_only       m.m1_i3
  2328. 20633 #define real_user_id  m.m1_i2
  2329. 20634 #define request       m.m1_i2
  2330. 20635 #define sig           m.m1_i2
  2331. 20636 #define slot1         m.m1_i1
  2332. 20637 #define tp            m.m2_l1
  2333. 20638 #define utime_actime  m.m2_l1
  2334. 20639 #define utime_modtime m.m2_l2
  2335. 20640 #define utime_file    m.m2_p1
  2336. 20641 #define utime_length  m.m2_i1
  2337. 20642 #define whence        m.m2_i2
  2338. 20643
  2339. 20644 /* The following names are synonyms for the variables in the output message. */
  2340. 20645 #define reply_type    m1.m_type
  2341. 20646 #define reply_l1      m1.m2_l1
  2342. 20647 #define reply_i1      m1.m1_i1
  2343. 20648 #define reply_i2      m1.m1_i2
  2344. 20649 #define reply_t1      m1.m4_l1
  2345. 20650 #define reply_t2      m1.m4_l2
  2346. 20651 #define reply_t3      m1.m4_l3
  2347. 20652 #define reply_t4      m1.m4_l4
  2348. 20653 #define reply_t5      m1.m4_l5
  2349. .Ep 280 src/fs/super.h
  2350. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2351. src/fs/super.h    
  2352. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2353. 20700 /* Super block table.  The root file system and every mounted file system
  2354. 20701  * has an entry here.  The entry holds information about the sizes of the bit
  2355. 20702  * maps and inodes.  The s_ninodes field gives the number of inodes available
  2356. 20703  * for files and directories, including the root directory.  Inode 0 is 
  2357. 20704  * on the disk, but not used.  Thus s_ninodes = 4 means that 5 bits will be
  2358. 20705  * used in the bit map, bit 0, which is always 1 and not used, and bits 1-4
  2359. 20706  * for files and directories.  The disk layout is:
  2360. 20707  *
  2361. 20708  *      Item        # blocks
  2362. 20709  *    boot block      1
  2363. 20710  *    super block     1
  2364. 20711  *    inode map     s_imap_blocks
  2365. 20712  *    zone map      s_zmap_blocks
  2366. 20713  *    inodes        (s_ninodes + 'inodes per block' - 1)/'inodes per block'
  2367. 20714  *    unused        whatever is needed to fill out the current zone
  2368. 20715  *    data zones    (s_zones - s_firstdatazone) << s_log_zone_size
  2369. 20716  *
  2370. 20717  * A super_block slot is free if s_dev == NO_DEV. 
  2371. 20718  */
  2372. 20719
  2373. 20720
  2374. 20721 EXTERN struct super_block {
  2375. 20722   ino_t s_ninodes;              /* # usable inodes on the minor device */
  2376. 20723   zone1_t  s_nzones;            /* total device size, including bit maps etc */
  2377. 20724   short s_imap_blocks;          /* # of blocks used by inode bit map */
  2378. 20725   short s_zmap_blocks;          /* # of blocks used by zone bit map */
  2379. 20726   zone1_t s_firstdatazone;      /* number of first data zone */
  2380. 20727   short s_log_zone_size;        /* log2 of blocks/zone */
  2381. 20728   off_t s_max_size;             /* maximum file size on this device */
  2382. 20729   short s_magic;                /* magic number to recognize super-blocks */
  2383. 20730   short s_pad;                  /* try to avoid compiler-dependent padding */
  2384. 20731   zone_t s_zones;               /* number of zones (replaces s_nzones in V2) */
  2385. 20732
  2386. 20733   /* The following items are only used when the super_block is in memory. */
  2387. 20734   struct inode *s_isup;         /* inode for root dir of mounted file sys */
  2388. 20735   struct inode *s_imount;       /* inode mounted on */
  2389. 20736   unsigned s_inodes_per_block;  /* precalculated from magic number */
  2390. 20737   dev_t s_dev;                  /* whose super block is this? */
  2391. 20738   int s_rd_only;                /* set to 1 iff file sys mounted read only */
  2392. 20739   int s_native;                 /* set to 1 iff not byte swapped file system */
  2393. 20740   int s_version;                /* file system version, zero means bad magic */
  2394. 20741   int s_ndzones;                /* # direct zones in an inode */
  2395. 20742   int s_nindirs;                /* # indirect zones per indirect block */
  2396. 20743   bit_t s_isearch;              /* inodes below this bit number are in use */
  2397. 20744   bit_t s_zsearch;              /* all zones below this bit number are in use*/
  2398. 20745 } super_block[NR_SUPERS];
  2399. 20746
  2400. 20747 #define NIL_SUPER (struct super_block *) 0
  2401. 20748 #define IMAP            0       /* operating on the inode bit map */
  2402. 20749 #define ZMAP            1       /* operating on the zone bit map */
  2403. .Op 281 src/fs/table.c
  2404. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2405. src/fs/table.c    
  2406. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2407. 20800 /* This file contains the table used to map system call numbers onto the
  2408. 20801  * routines that perform them.
  2409. 20802  */
  2410. 20803
  2411. 20804 #define _TABLE
  2412. 20805
  2413. 20806 #include "fs.h"
  2414. 20807 #include <minix/callnr.h>
  2415. 20808 #include <minix/com.h>
  2416. 20809 #include "buf.h"
  2417. 20810 #include "dev.h"
  2418. 20811 #include "file.h"
  2419. 20812 #include "fproc.h"
  2420. 20813 #include "inode.h"
  2421. 20814 #include "lock.h"
  2422. 20815 #include "super.h"
  2423. 20816
  2424. 20817 PUBLIC _PROTOTYPE (int (*call_vector[NCALLS]), (void) ) = {
  2425. 20818         no_sys,         /*  0 = unused  */
  2426. 20819         do_exit,        /*  1 = exit    */
  2427. 20820         do_fork,        /*  2 = fork    */
  2428. 20821         do_read,        /*  3 = read    */
  2429. 20822         do_write,       /*  4 = write   */
  2430. 20823         do_open,        /*  5 = open    */
  2431. 20824         do_close,       /*  6 = close   */
  2432. 20825         no_sys,         /*  7 = wait    */
  2433. 20826         do_creat,       /*  8 = creat   */
  2434. 20827         do_link,        /*  9 = link    */
  2435. 20828         do_unlink,      /* 10 = unlink  */
  2436. 20829         no_sys,         /* 11 = waitpid */
  2437. 20830         do_chdir,       /* 12 = chdir   */
  2438. 20831         do_time,        /* 13 = time    */
  2439. 20832         do_mknod,       /* 14 = mknod   */
  2440. 20833         do_chmod,       /* 15 = chmod   */
  2441. 20834         do_chown,       /* 16 = chown   */
  2442. 20835         no_sys,         /* 17 = break   */
  2443. 20836         do_stat,        /* 18 = stat    */
  2444. 20837         do_lseek,       /* 19 = lseek   */
  2445. 20838         no_sys,         /* 20 = getpid  */
  2446. 20839         do_mount,       /* 21 = mount   */
  2447. 20840         do_umount,      /* 22 = umount  */
  2448. 20841         do_set,         /* 23 = setuid  */
  2449. 20842         no_sys,         /* 24 = getuid  */
  2450. 20843         do_stime,       /* 25 = stime   */
  2451. 20844         no_sys,         /* 26 = ptrace  */
  2452. 20845         no_sys,         /* 27 = alarm   */
  2453. 20846         do_fstat,       /* 28 = fstat   */
  2454. 20847         no_sys,         /* 29 = pause   */
  2455. 20848         do_utime,       /* 30 = utime   */
  2456. 20849         no_sys,         /* 31 = (stty)  */
  2457. 20850         no_sys,         /* 32 = (gtty)  */
  2458. 20851         do_access,      /* 33 = access  */
  2459. 20852         no_sys,         /* 34 = (nice)  */
  2460. 20853         no_sys,         /* 35 = (ftime) */
  2461. 20854         do_sync,        /* 36 = sync    */
  2462. .Ep 282 src/fs/table.c
  2463. 20855         no_sys,         /* 37 = kill    */
  2464. 20856         do_rename,      /* 38 = rename  */
  2465. 20857         do_mkdir,       /* 39 = mkdir   */
  2466. 20858         do_unlink,      /* 40 = rmdir   */
  2467. 20859         do_dup,         /* 41 = dup     */
  2468. 20860         do_pipe,        /* 42 = pipe    */
  2469. 20861         do_tims,        /* 43 = times   */
  2470. 20862         no_sys,         /* 44 = (prof)  */
  2471. 20863         no_sys,         /* 45 = unused  */
  2472. 20864         do_set,         /* 46 = setgid  */
  2473. 20865         no_sys,         /* 47 = getgid  */
  2474. 20866         no_sys,         /* 48 = (signal)*/
  2475. 20867         no_sys,         /* 49 = unused  */
  2476. 20868         no_sys,         /* 50 = unused  */
  2477. 20869         no_sys,         /* 51 = (acct)  */
  2478. 20870         no_sys,         /* 52 = (phys)  */
  2479. 20871         no_sys,         /* 53 = (lock)  */
  2480. 20872         do_ioctl,       /* 54 = ioctl   */
  2481. 20873         do_fcntl,       /* 55 = fcntl   */
  2482. 20874         no_sys,         /* 56 = (mpx)   */
  2483. 20875         no_sys,         /* 57 = unused  */
  2484. 20876         no_sys,         /* 58 = unused  */
  2485. 20877         do_exec,        /* 59 = execve  */
  2486. 20878         do_umask,       /* 60 = umask   */
  2487. 20879         do_chroot,      /* 61 = chroot  */
  2488. 20880         do_setsid,      /* 62 = setsid  */
  2489. 20881         no_sys,         /* 63 = getpgrp */
  2490. 20882
  2491. 20883         no_sys,         /* 64 = KSIG: signals originating in the kernel */
  2492. 20884         do_unpause,     /* 65 = UNPAUSE */
  2493. 20885         no_sys,         /* 66 = unused  */
  2494. 20886         do_revive,      /* 67 = REVIVE  */
  2495. 20887         no_sys,         /* 68 = TASK_REPLY      */
  2496. 20888         no_sys,         /* 69 = unused */
  2497. 20889         no_sys,         /* 70 = unused */
  2498. 20890         no_sys,         /* 71 = SIGACTION */
  2499. 20891         no_sys,         /* 72 = SIGSUSPEND */
  2500. 20892         no_sys,         /* 73 = SIGPENDING */
  2501. 20893         no_sys,         /* 74 = SIGPROCMASK */
  2502. 20894         no_sys,         /* 75 = SIGRETURN */
  2503. 20895         no_sys,         /* 76 = REBOOT */
  2504. 20896 };
  2505. 20897
  2506. 20898
  2507. 20899 /* Some devices may or may not be there in the next table. */
  2508. 20900 #define DT(enable, open, rw, close, task) 
  2509. 20901         { (enable ? (open) : no_dev), (enable ? (rw) : no_dev), 
  2510. 20902           (enable ? (close) : no_dev), (enable ? (task) : 0) },
  2511. 20903
  2512. 20904 /* The order of the entries here determines the mapping between major device
  2513. 20905  * numbers and tasks.  The first entry (major device 0) is not used.  The
  2514. 20906  * next entry is major device 1, etc.  Character and block devices can be
  2515. 20907  * intermixed at random.  If this ordering is changed, the devices in
  2516. 20908  * <include/minix/boot.h> must be changed to correspond to the new values.
  2517. 20909  * Note that the major device numbers used in /dev are NOT the same as the 
  2518. 20910  * task numbers used inside the kernel (as defined in <include/minix/com.h>).
  2519. 20911  * Also note that if /dev/mem is changed from 1, NULL_MAJOR must be changed
  2520. 20912  * in <include/minix/com.h>.
  2521. 20913  */
  2522. 20914 PUBLIC struct dmap dmap[] = {
  2523. .Op 283 src/fs/table.c
  2524. 20915 /*  ?   Open       Read/Write   Close       Task #      Device  File
  2525. 20916     -   ----       ----------   -----       -------     ------  ----       */
  2526. 20917   DT(1, no_dev,    no_dev,      no_dev,     0)           /* 0 = not used   */
  2527. 20918   DT(1, dev_opcl,  call_task,   dev_opcl,   MEM)         /* 1 = /dev/mem   */
  2528. 20919   DT(1, dev_opcl,  call_task,   dev_opcl,   FLOPPY)      /* 2 = /dev/fd0   */
  2529. 20920   DT(ENABLE_WINI,
  2530. 20921         dev_opcl,  call_task,   dev_opcl,   WINCHESTER)  /* 3 = /dev/hd0   */
  2531. 20922   DT(1, tty_open,  call_task,   dev_opcl,   TTY)         /* 4 = /dev/tty00 */
  2532. 20923   DT(1, ctty_open, call_ctty,   ctty_close, TTY)         /* 5 = /dev/tty   */
  2533. 20924   DT(1, dev_opcl,  call_task,   dev_opcl,    PRINTER)     /* 6 = /dev/lp    */
  2534. 20925
  2535. 20926 #if (MACHINE == IBM_PC)
  2536. 20927   DT(ENABLE_NETWORKING,
  2537. 20928         net_open,  call_task,   dev_opcl,   INET_PROC_NR)/* 7 = /dev/ip    */
  2538. 20929   DT(ENABLE_CDROM,
  2539. 20930         dev_opcl,  call_task,   dev_opcl,   CDROM)       /* 8 = /dev/cd0   */
  2540. 20931   DT(0, 0,         0,           0,          0)           /* 9 = not used   */
  2541. 20932   DT(ENABLE_SCSI,
  2542. 20933         dev_opcl,  call_task,   dev_opcl,   SCSI)        /*10 = /dev/sd0   */
  2543. 20934   DT(0, 0,         0,           0,          0)           /*11 = not used   */
  2544. 20935   DT(0, 0,         0,           0,          0)           /*12 = not used   */
  2545. 20936   DT(ENABLE_AUDIO,
  2546. 20937         dev_opcl,  call_task,   dev_opcl,   AUDIO)       /*13 = /dev/audio */
  2547. 20938   DT(ENABLE_AUDIO,
  2548. 20939         dev_opcl,  call_task,   dev_opcl,   MIXER)       /*14 = /dev/mixer */
  2549. 20940 #endif /* IBM_PC */
  2550. 20941
  2551. 20942 #if (MACHINE == ATARI)
  2552. 20943   DT(ENABLE_SCSI,
  2553. 20944         dev_opcl,  call_task,   dev_opcl,   SCSI)        /* 7 = /dev/hdscsi0 */
  2554. 20945 #endif
  2555. 20946 };
  2556. 20947
  2557. 20948 PUBLIC int max_major = sizeof(dmap)/sizeof(struct dmap);
  2558. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2559. src/fs/cache.c    
  2560. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2561. 21000 /* The file system maintains a buffer cache to reduce the number of disk
  2562. 21001  * accesses needed.  Whenever a read or write to the disk is done, a check is
  2563. 21002  * first made to see if the block is in the cache.  This file manages the
  2564. 21003  * cache.
  2565. 21004  *
  2566. 21005  * The entry points into this file are:
  2567. 21006  *   get_block:   request to fetch a block for reading or writing from cache
  2568. 21007  *   put_block:   return a block previously requested with get_block
  2569. 21008  *   alloc_zone:  allocate a new zone (to increase the length of a file)
  2570. 21009  *   free_zone:   release a zone (when a file is removed)
  2571. 21010  *   rw_block:    read or write a block from the disk itself
  2572. 21011  *   invalidate:  remove all the cache blocks on some device
  2573. 21012  */
  2574. 21013
  2575. 21014 #include "fs.h"
  2576. 21015 #include <minix/com.h>
  2577. 21016 #include <minix/boot.h>
  2578. 21017 #include "buf.h"
  2579. 21018 #include "file.h"
  2580. 21019 #include "fproc.h"
  2581. .Ep 284 src/fs/cache.c
  2582. 21020 #include "super.h"
  2583. 21021
  2584. 21022 FORWARD _PROTOTYPE( void rm_lru, (struct buf *bp) );
  2585. 21023
  2586. 21024 /*===========================================================================*
  2587. 21025  *                              get_block                                    *
  2588. 21026  *===========================================================================*/
  2589. 21027 PUBLIC struct buf *get_block(dev, block, only_search)
  2590. 21028 register dev_t dev;             /* on which device is the block? */
  2591. 21029 register block_t block;         /* which block is wanted? */
  2592. 21030 int only_search;                /* if NO_READ, don't read, else act normal */
  2593. 21031 {
  2594. 21032 /* Check to see if the requested block is in the block cache.  If so, return
  2595. 21033  * a pointer to it.  If not, evict some other block and fetch it (unless
  2596. 21034  * 'only_search' is 1).  All the blocks in the cache that are not in use
  2597. 21035  * are linked together in a chain, with 'front' pointing to the least recently
  2598. 21036  * used block and 'rear' to the most recently used block.  If 'only_search' is
  2599. 21037  * 1, the block being requested will be overwritten in its entirety, so it is
  2600. 21038  * only necessary to see if it is in the cache; if it is not, any free buffer
  2601. 21039  * will do.  It is not necessary to actually read the block in from disk.
  2602. 21040  * If 'only_search' is PREFETCH, the block need not be read from the disk,
  2603. 21041  * and the device is not to be marked on the block, so callers can tell if
  2604. 21042  * the block returned is valid.
  2605. 21043  * In addition to the LRU chain, there is also a hash chain to link together
  2606. 21044  * blocks whose block numbers end with the same bit strings, for fast lookup.
  2607. 21045  */
  2608. 21046
  2609. 21047   int b;
  2610. 21048   register struct buf *bp, *prev_ptr;
  2611. 21049
  2612. 21050   /* Search the hash chain for (dev, block). Do_read() can use 
  2613. 21051    * get_block(NO_DEV ...) to get an unnamed block to fill with zeros when
  2614. 21052    * someone wants to read from a hole in a file, in which case this search
  2615. 21053    * is skipped
  2616. 21054    */
  2617. 21055   if (dev != NO_DEV) {
  2618. 21056         b = (int) block & HASH_MASK;
  2619. 21057         bp = buf_hash[b];
  2620. 21058         while (bp != NIL_BUF) {
  2621. 21059                 if (bp->b_blocknr == block && bp->b_dev == dev) {
  2622. 21060                         /* Block needed has been found. */
  2623. 21061                         if (bp->b_count == 0) rm_lru(bp);
  2624. 21062                         bp->b_count++;  /* record that block is in use */
  2625. 21063                         return(bp);
  2626. 21064                 } else {
  2627. 21065                         /* This block is not the one sought. */
  2628. 21066                         bp = bp->b_hash; /* move to next block on hash chain */
  2629. 21067                 }
  2630. 21068         }
  2631. 21069   }
  2632. 21070
  2633. 21071   /* Desired block is not on available chain.  Take oldest block ('front'). */
  2634. 21072   if ((bp = front) == NIL_BUF) panic("all buffers in use", NR_BUFS);
  2635. 21073   rm_lru(bp);
  2636. 21074
  2637. 21075   /* Remove the block that was just taken from its hash chain. */
  2638. 21076   b = (int) bp->b_blocknr & HASH_MASK;
  2639. 21077   prev_ptr = buf_hash[b];
  2640. 21078   if (prev_ptr == bp) {
  2641. 21079         buf_hash[b] = bp->b_hash;
  2642. .Op 285 src/fs/cache.c
  2643. 21080   } else {
  2644. 21081         /* The block just taken is not on the front of its hash chain. */
  2645. 21082         while (prev_ptr->b_hash != NIL_BUF)
  2646. 21083                 if (prev_ptr->b_hash == bp) {
  2647. 21084                         prev_ptr->b_hash = bp->b_hash;  /* found it */
  2648. 21085                         break;
  2649. 21086                 } else {
  2650. 21087                         prev_ptr = prev_ptr->b_hash;    /* keep looking */
  2651. 21088                 }
  2652. 21089   }
  2653. 21090
  2654. 21091   /* If the block taken is dirty, make it clean by writing it to the disk.
  2655. 21092    * Avoid hysteresis by flushing all other dirty blocks for the same device.
  2656. 21093    */
  2657. 21094   if (bp->b_dev != NO_DEV) {
  2658. 21095         if (bp->b_dirt == DIRTY) flushall(bp->b_dev);
  2659. 21096   }
  2660. 21097
  2661. 21098   /* Fill in block's parameters and add it to the hash chain where it goes. */
  2662. 21099   bp->b_dev = dev;              /* fill in device number */
  2663. 21100   bp->b_blocknr = block;        /* fill in block number */
  2664. 21101   bp->b_count++;                /* record that block is being used */
  2665. 21102   b = (int) bp->b_blocknr & HASH_MASK;
  2666. 21103   bp->b_hash = buf_hash[b];
  2667. 21104   buf_hash[b] = bp;             /* add to hash list */
  2668. 21105
  2669. 21106   /* Go get the requested block unless searching or prefetching. */
  2670. 21107   if (dev != NO_DEV) {
  2671. 21108         if (only_search == PREFETCH) bp->b_dev = NO_DEV;
  2672. 21109         else
  2673. 21110         if (only_search == NORMAL) rw_block(bp, READING);
  2674. 21111   }
  2675. 21112   return(bp);                   /* return the newly acquired block */
  2676. 21113 }
  2677. 21116 /*===========================================================================*
  2678. 21117  *                              put_block                                    *
  2679. 21118  *===========================================================================*/
  2680. 21119 PUBLIC void put_block(bp, block_type)
  2681. 21120 register struct buf *bp;        /* pointer to the buffer to be released */
  2682. 21121 int block_type;                 /* INODE_BLOCK, DIRECTORY_BLOCK, or whatever */
  2683. 21122 {
  2684. 21123 /* Return a block to the list of available blocks.   Depending on 'block_type'
  2685. 21124  * it may be put on the front or rear of the LRU chain.  Blocks that are
  2686. 21125  * expected to be needed again shortly (e.g., partially full data blocks)
  2687. 21126  * go on the rear; blocks that are unlikely to be needed again shortly
  2688. 21127  * (e.g., full data blocks) go on the front.  Blocks whose loss can hurt
  2689. 21128  * the integrity of the file system (e.g., inode blocks) are written to
  2690. 21129  * disk immediately if they are dirty.
  2691. 21130  */
  2692. 21131
  2693. 21132   if (bp == NIL_BUF) return;    /* it is easier to check here than in caller */
  2694. 21133
  2695. 21134   bp->b_count--;                /* there is one use fewer now */
  2696. 21135   if (bp->b_count != 0) return; /* block is still in use */
  2697. 21136
  2698. 21137   bufs_in_use--;                /* one fewer block buffers in use */
  2699. 21138
  2700. 21139   /* Put this block back on the LRU chain.  If the ONE_SHOT bit is set in
  2701. .Ep 286 src/fs/cache.c
  2702. 21140    * 'block_type', the block is not likely to be needed again shortly, so put
  2703. 21141    * it on the front of the LRU chain where it will be the first one to be
  2704. 21142    * taken when a free buffer is needed later.
  2705. 21143    */
  2706. 21144   if (block_type & ONE_SHOT) {
  2707. 21145         /* Block probably won't be needed quickly. Put it on front of chain.
  2708. 21146          * It will be the next block to be evicted from the cache.
  2709. 21147          */
  2710. 21148         bp->b_prev = NIL_BUF;
  2711. 21149         bp->b_next = front;
  2712. 21150         if (front == NIL_BUF)
  2713. 21151                 rear = bp;      /* LRU chain was empty */
  2714. 21152         else
  2715. 21153                 front->b_prev = bp;
  2716. 21154         front = bp;
  2717. 21155   } else {
  2718. 21156         /* Block probably will be needed quickly.  Put it on rear of chain.
  2719. 21157          * It will not be evicted from the cache for a long time.
  2720. 21158          */
  2721. 21159         bp->b_prev = rear;
  2722. 21160         bp->b_next = NIL_BUF;
  2723. 21161         if (rear == NIL_BUF)
  2724. 21162                 front = bp;
  2725. 21163         else
  2726. 21164                 rear->b_next = bp;
  2727. 21165         rear = bp;
  2728. 21166   }
  2729. 21167
  2730. 21168   /* Some blocks are so important (e.g., inodes, indirect blocks) that they
  2731. 21169    * should be written to the disk immediately to avoid messing up the file
  2732. 21170    * system in the event of a crash.
  2733. 21171    */
  2734. 21172   if ((block_type & WRITE_IMMED) && bp->b_dirt==DIRTY && bp->b_dev != NO_DEV)
  2735. 21173         rw_block(bp, WRITING);
  2736. 21174 }
  2737. 21177 /*===========================================================================*
  2738. 21178  *                              alloc_zone                                   *
  2739. 21179  *===========================================================================*/
  2740. 21180 PUBLIC zone_t alloc_zone(dev, z)
  2741. 21181 dev_t dev;                      /* device where zone wanted */
  2742. 21182 zone_t z;                       /* try to allocate new zone near this one */
  2743. 21183 {
  2744. 21184 /* Allocate a new zone on the indicated device and return its number. */
  2745. 21185
  2746. 21186   int major, minor;
  2747. 21187   bit_t b, bit;
  2748. 21188   struct super_block *sp;
  2749. 21189
  2750. 21190   /* Note that the routine alloc_bit() returns 1 for the lowest possible