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

操作系统开发

开发平台:

C/C++

  1. 24308  *   pipe_check:  check to see that a read or write on a pipe is feasible now
  2. 24309  *   suspend:     suspend a process that cannot do a requested read or write
  3. 24310  *   release:     check to see if a suspended process can be released and do it
  4. 24311  *   revive:      mark a suspended process as able to run again
  5. 24312  *   do_unpause:  a signal has been sent to a process; see if it suspended
  6. 24313  */
  7. 24314
  8. 24315 #include "fs.h"
  9. 24316 #include <fcntl.h>
  10. 24317 #include <signal.h>
  11. 24318 #include <minix/boot.h>
  12. 24319 #include <minix/callnr.h>
  13. 24320 #include <minix/com.h>
  14. 24321 #include "dev.h"
  15. 24322 #include "file.h"
  16. 24323 #include "fproc.h"
  17. 24324 #include "inode.h"
  18. 24325 #include "param.h"
  19. 24326
  20. 24327 PRIVATE message mess;
  21. 24328
  22. 24329 /*===========================================================================*
  23. 24330  *                              do_pipe                                      *
  24. 24331  *===========================================================================*/
  25. 24332 PUBLIC int do_pipe()
  26. 24333 {
  27. 24334 /* Perform the pipe(fil_des) system call. */
  28. 24335
  29. 24336   register struct fproc *rfp;
  30. 24337   register struct inode *rip;
  31. 24338   int r;
  32. 24339   struct filp *fil_ptr0, *fil_ptr1;
  33. 24340   int fil_des[2];               /* reply goes here */
  34. 24341
  35. 24342   /* Acquire two file descriptors. */
  36. 24343   rfp = fp;
  37. 24344   if ( (r = get_fd(0, R_BIT, &fil_des[0], &fil_ptr0)) != OK) return(r);
  38. 24345   rfp->fp_filp[fil_des[0]] = fil_ptr0;
  39. 24346   fil_ptr0->filp_count = 1;
  40. 24347   if ( (r = get_fd(0, W_BIT, &fil_des[1], &fil_ptr1)) != OK) {
  41. 24348         rfp->fp_filp[fil_des[0]] = NIL_FILP;
  42. 24349         fil_ptr0->filp_count = 0;
  43. .Op 335 src/fs/pipe.c
  44. 24350         return(r);
  45. 24351   }
  46. 24352   rfp->fp_filp[fil_des[1]] = fil_ptr1;
  47. 24353   fil_ptr1->filp_count = 1;
  48. 24354
  49. 24355   /* Make the inode on the pipe device. */
  50. 24356   if ( (rip = alloc_inode(PIPE_DEV, I_REGULAR) ) == NIL_INODE) {
  51. 24357         rfp->fp_filp[fil_des[0]] = NIL_FILP;
  52. 24358         fil_ptr0->filp_count = 0;
  53. 24359         rfp->fp_filp[fil_des[1]] = NIL_FILP;
  54. 24360         fil_ptr1->filp_count = 0;
  55. 24361         return(err_code);
  56. 24362   }
  57. 24363
  58. 24364   if (read_only(rip) != OK) panic("pipe device is read only", NO_NUM);
  59. 24365  
  60. 24366   rip->i_pipe = I_PIPE;
  61. 24367   rip->i_mode &= ~I_REGULAR;
  62. 24368   rip->i_mode |= I_NAMED_PIPE;  /* pipes and FIFOs have this bit set */
  63. 24369   fil_ptr0->filp_ino = rip;
  64. 24370   fil_ptr0->filp_flags = O_RDONLY;
  65. 24371   dup_inode(rip);               /* for double usage */
  66. 24372   fil_ptr1->filp_ino = rip;
  67. 24373   fil_ptr1->filp_flags = O_WRONLY;
  68. 24374   rw_inode(rip, WRITING);       /* mark inode as allocated */
  69. 24375   reply_i1 = fil_des[0];
  70. 24376   reply_i2 = fil_des[1];
  71. 24377   rip->i_update = ATIME | CTIME | MTIME;
  72. 24378   return(OK);
  73. 24379 }
  74. 24382 /*===========================================================================*
  75. 24383  *                              pipe_check                                   *
  76. 24384  *===========================================================================*/
  77. 24385 PUBLIC int pipe_check(rip, rw_flag, oflags, bytes, position, canwrite)
  78. 24386 register struct inode *rip;     /* the inode of the pipe */
  79. 24387 int rw_flag;                    /* READING or WRITING */
  80. 24388 int oflags;                     /* flags set by open or fcntl */
  81. 24389 register int bytes;             /* bytes to be read or written (all chunks) */
  82. 24390 register off_t position;        /* current file position */
  83. 24391 int *canwrite;                  /* return: number of bytes we can write */
  84. 24392 {
  85. 24393 /* Pipes are a little different.  If a process reads from an empty pipe for
  86. 24394  * which a writer still exists, suspend the reader.  If the pipe is empty
  87. 24395  * and there is no writer, return 0 bytes.  If a process is writing to a
  88. 24396  * pipe and no one is reading from it, give a broken pipe error.
  89. 24397  */
  90. 24398
  91. 24399   int r = 0;
  92. 24400
  93. 24401   /* If reading, check for empty pipe. */
  94. 24402   if (rw_flag == READING) {
  95. 24403         if (position >= rip->i_size) {
  96. 24404                 /* Process is reading from an empty pipe. */
  97. 24405                 if (find_filp(rip, W_BIT) != NIL_FILP) {
  98. 24406                         /* Writer exists */
  99. 24407                         if (oflags & O_NONBLOCK) 
  100. 24408                                 r = EAGAIN;
  101. 24409                         else 
  102. .Ep 336 src/fs/pipe.c
  103. 24410                                 suspend(XPIPE); /* block reader */
  104. 24411
  105. 24412                         /* If need be, activate sleeping writers. */
  106. 24413                         if (susp_count > 0) release(rip, WRITE, susp_count);
  107. 24414                 }
  108. 24415                 return(r);
  109. 24416         }
  110. 24417   } else {
  111. 24418         /* Process is writing to a pipe. */
  112. 24419 /*      if (bytes > PIPE_SIZE) return(EFBIG); */
  113. 24420         if (find_filp(rip, R_BIT) == NIL_FILP) {
  114. 24421                 /* Tell kernel to generate a SIGPIPE signal. */
  115. 24422                 sys_kill((int)(fp - fproc), SIGPIPE);
  116. 24423                 return(EPIPE);
  117. 24424         }
  118. 24425
  119. 24426         if (position + bytes > PIPE_SIZE) {
  120. 24427                 if ((oflags & O_NONBLOCK) && bytes < PIPE_SIZE) 
  121. 24428                         return(EAGAIN);
  122. 24429                 else if ((oflags & O_NONBLOCK) && bytes > PIPE_SIZE) {
  123. 24430                         if ( (*canwrite = (PIPE_SIZE - position)) > 0)  {
  124. 24431                                 /* Do a partial write. Need to wakeup reader */
  125. 24432                                 release(rip, READ, susp_count);
  126. 24433                                 return(1);
  127. 24434                         } else {
  128. 24435                                 return(EAGAIN);
  129. 24436                         }
  130. 24437                      }
  131. 24438                 if (bytes > PIPE_SIZE) {
  132. 24439                         if ((*canwrite = PIPE_SIZE - position) > 0) {
  133. 24440                                 /* Do a partial write. Need to wakeup reader
  134. 24441                                  * since we'll suspend ourself in read_write()
  135. 24442                                  */
  136. 24443                                 release(rip, READ, susp_count);
  137. 24444                                 return(1);
  138. 24445                         }
  139. 24446                 }
  140. 24447                 suspend(XPIPE); /* stop writer -- pipe full */
  141. 24448                 return(0);
  142. 24449         }
  143. 24450
  144. 24451         /* Writing to an empty pipe.  Search for suspended reader. */
  145. 24452         if (position == 0) release(rip, READ, susp_count);
  146. 24453   }
  147. 24454
  148. 24455   *canwrite = 0;
  149. 24456   return(1);
  150. 24457 }
  151. 24460 /*===========================================================================*
  152. 24461  *                              suspend                                      *
  153. 24462  *===========================================================================*/
  154. 24463 PUBLIC void suspend(task)
  155. 24464 int task;                       /* who is proc waiting for? (PIPE = pipe) */
  156. 24465 {
  157. 24466 /* Take measures to suspend the processing of the present system call.
  158. 24467  * Store the parameters to be used upon resuming in the process table.
  159. 24468  * (Actually they are not used when a process is waiting for an I/O device,
  160. 24469  * but they are needed for pipes, and it is not worth making the distinction.)
  161. .Op 337 src/fs/pipe.c
  162. 24470  */
  163. 24471
  164. 24472   if (task == XPIPE || task == XPOPEN) susp_count++;/* #procs susp'ed on pipe*/
  165. 24473   fp->fp_suspended = SUSPENDED;
  166. 24474   fp->fp_fd = fd << 8 | fs_call;
  167. 24475   fp->fp_task = -task;
  168. 24476   if (task == XLOCK) {
  169. 24477         fp->fp_buffer = (char *) name1; /*  third arg to fcntl() */
  170. 24478         fp->fp_nbytes =request;         /* second arg to fcntl() */
  171. 24479   } else {
  172. 24480         fp->fp_buffer = buffer;         /* for reads and writes */
  173. 24481         fp->fp_nbytes = nbytes;
  174. 24482   }
  175. 24483   dont_reply = TRUE;            /* do not send caller a reply message now */
  176. 24484 }
  177. 24487 /*===========================================================================*
  178. 24488  *                              release                                      *
  179. 24489  *===========================================================================*/
  180. 24490 PUBLIC void release(ip, call_nr, count)
  181. 24491 register struct inode *ip;      /* inode of pipe */
  182. 24492 int call_nr;                    /* READ, WRITE, OPEN or CREAT */
  183. 24493 int count;                      /* max number of processes to release */
  184. 24494 {
  185. 24495 /* Check to see if any process is hanging on the pipe whose inode is in 'ip'.
  186. 24496  * If one is, and it was trying to perform the call indicated by 'call_nr',
  187. 24497  * release it.
  188. 24498  */
  189. 24499
  190. 24500   register struct fproc *rp;
  191. 24501
  192. 24502   /* Search the proc table. */
  193. 24503   for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++) {
  194. 24504         if (rp->fp_suspended == SUSPENDED &&
  195. 24505                         rp->fp_revived == NOT_REVIVING &&
  196. 24506                         (rp->fp_fd & BYTE) == call_nr &&
  197. 24507                         rp->fp_filp[rp->fp_fd>>8]->filp_ino == ip) {
  198. 24508                 revive((int)(rp - fproc), 0);
  199. 24509                 susp_count--;   /* keep track of who is suspended */
  200. 24510                 if (--count == 0) return;
  201. 24511         }
  202. 24512   }
  203. 24513 }
  204. 24516 /*===========================================================================*
  205. 24517  *                              revive                                       *
  206. 24518  *===========================================================================*/
  207. 24519 PUBLIC void revive(proc_nr, bytes)
  208. 24520 int proc_nr;                    /* process to revive */
  209. 24521 int bytes;                      /* if hanging on task, how many bytes read */
  210. 24522 {
  211. 24523 /* Revive a previously blocked process. When a process hangs on tty, this
  212. 24524  * is the way it is eventually released.
  213. 24525  */
  214. 24526
  215. 24527   register struct fproc *rfp;
  216. 24528   register int task;
  217. 24529
  218. .Ep 338 src/fs/pipe.c
  219. 24530   if (proc_nr < 0 || proc_nr >= NR_PROCS) panic("revive err", proc_nr);
  220. 24531   rfp = &fproc[proc_nr];
  221. 24532   if (rfp->fp_suspended == NOT_SUSPENDED || rfp->fp_revived == REVIVING)return;
  222. 24533
  223. 24534   /* The 'reviving' flag only applies to pipes.  Processes waiting for TTY get
  224. 24535    * a message right away.  The revival process is different for TTY and pipes.
  225. 24536    * For TTY revival, the work is already done, for pipes it is not: the proc
  226. 24537    * must be restarted so it can try again.
  227. 24538    */
  228. 24539   task = -rfp->fp_task;
  229. 24540   if (task == XPIPE || task == XLOCK) {
  230. 24541         /* Revive a process suspended on a pipe or lock. */
  231. 24542         rfp->fp_revived = REVIVING;
  232. 24543         reviving++;             /* process was waiting on pipe or lock */
  233. 24544   } else {
  234. 24545         rfp->fp_suspended = NOT_SUSPENDED;
  235. 24546         if (task == XPOPEN) /* process blocked in open or create */
  236. 24547                 reply(proc_nr, rfp->fp_fd>>8);
  237. 24548         else {
  238. 24549                 /* Revive a process suspended on TTY or other device. */
  239. 24550                 rfp->fp_nbytes = bytes; /*pretend it wants only what there is*/
  240. 24551                 reply(proc_nr, bytes);  /* unblock the process */
  241. 24552         }
  242. 24553   }
  243. 24554 }
  244. 24557 /*===========================================================================*
  245. 24558  *                              do_unpause                                   *
  246. 24559  *===========================================================================*/
  247. 24560 PUBLIC int do_unpause()
  248. 24561 {
  249. 24562 /* A signal has been sent to a user who is paused on the file system.
  250. 24563  * Abort the system call with the EINTR error message.
  251. 24564  */
  252. 24565
  253. 24566   register struct fproc *rfp;
  254. 24567   int proc_nr, task, fild;
  255. 24568   struct filp *f;
  256. 24569   dev_t dev;
  257. 24570
  258. 24571   if (who > MM_PROC_NR) return(EPERM);
  259. 24572   proc_nr = pro;
  260. 24573   if (proc_nr < 0 || proc_nr >= NR_PROCS) panic("unpause err 1", proc_nr);
  261. 24574   rfp = &fproc[proc_nr];
  262. 24575   if (rfp->fp_suspended == NOT_SUSPENDED) return(OK);
  263. 24576   task = -rfp->fp_task;
  264. 24577
  265. 24578   switch(task) {
  266. 24579         case XPIPE:             /* process trying to read or write a pipe */
  267. 24580                 break;
  268. 24581
  269. 24582         case XOPEN:             /* process trying to open a special file */
  270. 24583                 panic ("fs/do_unpause called with XOPENn", NO_NUM);
  271. 24584
  272. 24585         case XLOCK:             /* process trying to set a lock with FCNTL */
  273. 24586                 break;
  274. 24587
  275. 24588         case XPOPEN:            /* process trying to open a fifo */
  276. 24589                 break;
  277. .Op 339 src/fs/pipe.c
  278. 24590
  279. 24591         default:                /* process trying to do device I/O (e.g. tty)*/
  280. 24592                 fild = (rfp->fp_fd >> 8) & BYTE;/* extract file descriptor */
  281. 24593                 if (fild < 0 || fild >= OPEN_MAX)panic("unpause err 2",NO_NUM);
  282. 24594                 f = rfp->fp_filp[fild];
  283. 24595                 dev = (dev_t) f->filp_ino->i_zone[0];   /* device hung on */
  284. 24596                 mess.TTY_LINE = (dev >> MINOR) & BYTE;
  285. 24597                 mess.PROC_NR = proc_nr;
  286. 24598
  287. 24599                 /* Tell kernel R or W. Mode is from current call, not open. */
  288. 24600                 mess.COUNT = (rfp->fp_fd & BYTE) == READ ? R_BIT : W_BIT;
  289. 24601                 mess.m_type = CANCEL;
  290. 24602                 fp = rfp;       /* hack - call_ctty uses fp */
  291. 24603                 (*dmap[(dev >> MAJOR) & BYTE].dmap_rw)(task, &mess);
  292. 24604   }
  293. 24605
  294. 24606   rfp->fp_suspended = NOT_SUSPENDED;
  295. 24607   reply(proc_nr, EINTR);        /* signal interrupted call */
  296. 24608   return(OK);
  297. 24609 }
  298. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  299. src/fs/path.c    
  300. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  301. 24700 /* This file contains the procedures that look up path names in the directory
  302. 24701  * system and determine the inode number that goes with a given path name.
  303. 24702  *
  304. 24703  *  The entry points into this file are
  305. 24704  *   eat_path:   the 'main' routine of the path-to-inode conversion mechanism
  306. 24705  *   last_dir:   find the final directory on a given path
  307. 24706  *   advance:    parse one component of a path name
  308. 24707  *   search_dir: search a directory for a string and return its inode number
  309. 24708  */
  310. 24709
  311. 24710 #include "fs.h"
  312. 24711 #include <string.h>
  313. 24712 #include <minix/callnr.h>
  314. 24713 #include "buf.h"
  315. 24714 #include "file.h"
  316. 24715 #include "fproc.h"
  317. 24716 #include "inode.h"
  318. 24717 #include "super.h"
  319. 24718
  320. 24719 PUBLIC char dot1[2] = ".";      /* used for search_dir to bypass the access */
  321. 24720 PUBLIC char dot2[3] = "..";     /* permissions for . and ..                 */
  322. 24721
  323. 24722 FORWARD _PROTOTYPE( char *get_name, (char *old_name, char string [NAME_MAX]) );
  324. 24723
  325. 24724 /*===========================================================================*
  326. 24725  *                              eat_path                                     *
  327. 24726  *===========================================================================*/
  328. 24727 PUBLIC struct inode *eat_path(path)
  329. 24728 char *path;                     /* the path name to be parsed */
  330. 24729 {
  331. .Ep 340 src/fs/path.c
  332. 24730 /* Parse the path 'path' and put its inode in the inode table. If not possible,
  333. 24731  * return NIL_INODE as function value and an error code in 'err_code'.
  334. 24732  */
  335. 24733
  336. 24734   register struct inode *ldip, *rip;
  337. 24735   char string[NAME_MAX];        /* hold 1 path component name here */
  338. 24736
  339. 24737   /* First open the path down to the final directory. */
  340. 24738   if ( (ldip = last_dir(path, string)) == NIL_INODE)
  341. 24739         return(NIL_INODE);      /* we couldn't open final directory */
  342. 24740
  343. 24741   /* The path consisting only of "/" is a special case, check for it. */
  344. 24742   if (string[0] == '') return(ldip);
  345. 24743
  346. 24744   /* Get final component of the path. */
  347. 24745   rip = advance(ldip, string);
  348. 24746   put_inode(ldip);
  349. 24747   return(rip);
  350. 24748 }
  351. 24751 /*===========================================================================*
  352. 24752  *                              last_dir                                     *
  353. 24753  *===========================================================================*/
  354. 24754 PUBLIC struct inode *last_dir(path, string)
  355. 24755 char *path;                     /* the path name to be parsed */
  356. 24756 char string[NAME_MAX];          /* the final component is returned here */
  357. 24757 {
  358. 24758 /* Given a path, 'path', located in the fs address space, parse it as
  359. 24759  * far as the last directory, fetch the inode for the last directory into
  360. 24760  * the inode table, and return a pointer to the inode.  In
  361. 24761  * addition, return the final component of the path in 'string'.
  362. 24762  * If the last directory can't be opened, return NIL_INODE and
  363. 24763  * the reason for failure in 'err_code'.
  364. 24764  */
  365. 24765
  366. 24766   register struct inode *rip;
  367. 24767   register char *new_name;
  368. 24768   register struct inode *new_ip;
  369. 24769
  370. 24770   /* Is the path absolute or relative?  Initialize 'rip' accordingly. */
  371. 24771   rip = (*path == '/' ? fp->fp_rootdir : fp->fp_workdir);
  372. 24772
  373. 24773   /* If dir has been removed or path is empty, return ENOENT. */
  374. 24774   if (rip->i_nlinks == 0 || *path == '') {
  375. 24775         err_code = ENOENT;
  376. 24776         return(NIL_INODE);
  377. 24777   }
  378. 24778
  379. 24779   dup_inode(rip);               /* inode will be returned with put_inode */
  380. 24780
  381. 24781   /* Scan the path component by component. */
  382. 24782   while (TRUE) {
  383. 24783         /* Extract one component. */
  384. 24784         if ( (new_name = get_name(path, string)) == (char*) 0) {
  385. 24785                 put_inode(rip); /* bad path in user space */
  386. 24786                 return(NIL_INODE);
  387. 24787         }
  388. 24788         if (*new_name == '')
  389. 24789                 if ( (rip->i_mode & I_TYPE) == I_DIRECTORY)
  390. .Op 341 src/fs/path.c
  391. 24790                         return(rip);    /* normal exit */
  392. 24791                 else {
  393. 24792                         /* last file of path prefix is not a directory */
  394. 24793                         put_inode(rip);
  395. 24794                         err_code = ENOTDIR;                     
  396. 24795                         return(NIL_INODE);
  397. 24796                 }
  398. 24797
  399. 24798         /* There is more path.  Keep parsing. */
  400. 24799         new_ip = advance(rip, string);
  401. 24800         put_inode(rip);         /* rip either obsolete or irrelevant */
  402. 24801         if (new_ip == NIL_INODE) return(NIL_INODE);
  403. 24802
  404. 24803         /* The call to advance() succeeded.  Fetch next component. */
  405. 24804         path = new_name;
  406. 24805         rip = new_ip;
  407. 24806   }
  408. 24807 }
  409. 24810 /*===========================================================================*
  410. 24811  *                              get_name                                     *
  411. 24812  *===========================================================================*/
  412. 24813 PRIVATE char *get_name(old_name, string)
  413. 24814 char *old_name;                 /* path name to parse */
  414. 24815 char string[NAME_MAX];          /* component extracted from 'old_name' */
  415. 24816 {
  416. 24817 /* Given a pointer to a path name in fs space, 'old_name', copy the next
  417. 24818  * component to 'string' and pad with zeros.  A pointer to that part of
  418. 24819  * the name as yet unparsed is returned.  Roughly speaking,
  419. 24820  * 'get_name' = 'old_name' - 'string'.
  420. 24821  *
  421. 24822  * This routine follows the standard convention that /usr/ast, /usr//ast,
  422. 24823  * //usr///ast and /usr/ast/ are all equivalent.
  423. 24824  */
  424. 24825
  425. 24826   register int c;
  426. 24827   register char *np, *rnp;
  427. 24828
  428. 24829   np = string;                  /* 'np' points to current position */
  429. 24830   rnp = old_name;               /* 'rnp' points to unparsed string */
  430. 24831   while ( (c = *rnp) == '/') rnp++;     /* skip leading slashes */
  431. 24832
  432. 24833   /* Copy the unparsed path, 'old_name', to the array, 'string'. */
  433. 24834   while ( rnp < &old_name[PATH_MAX]  &&  c != '/'   &&  c != '') {
  434. 24835         if (np < &string[NAME_MAX]) *np++ = c;
  435. 24836         c = *++rnp;             /* advance to next character */
  436. 24837   }
  437. 24838
  438. 24839   /* To make /usr/ast/ equivalent to /usr/ast, skip trailing slashes. */
  439. 24840   while (c == '/' && rnp < &old_name[PATH_MAX]) c = *++rnp;
  440. 24841
  441. 24842   if (np < &string[NAME_MAX]) *np = '';       /* Terminate string */
  442. 24843
  443. 24844   if (rnp >= &old_name[PATH_MAX]) {
  444. 24845         err_code = ENAMETOOLONG;
  445. 24846         return((char *) 0);
  446. 24847   }
  447. 24848   return(rnp);
  448. 24849 }
  449. .Ep 342 src/fs/path.c
  450. 24852 /*===========================================================================*
  451. 24853  *                              advance                                      *
  452. 24854  *===========================================================================*/
  453. 24855 PUBLIC struct inode *advance(dirp, string)
  454. 24856 struct inode *dirp;             /* inode for directory to be searched */
  455. 24857 char string[NAME_MAX];          /* component name to look for */
  456. 24858 {
  457. 24859 /* Given a directory and a component of a path, look up the component in
  458. 24860  * the directory, find the inode, open it, and return a pointer to its inode
  459. 24861  * slot.  If it can't be done, return NIL_INODE.
  460. 24862  */
  461. 24863
  462. 24864   register struct inode *rip;
  463. 24865   struct inode *rip2;
  464. 24866   register struct super_block *sp;
  465. 24867   int r, inumb;
  466. 24868   dev_t mnt_dev;
  467. 24869   ino_t numb;
  468. 24870
  469. 24871   /* If 'string' is empty, yield same inode straight away. */
  470. 24872   if (string[0] == '') return(get_inode(dirp->i_dev, (int) dirp->i_num));
  471. 24873
  472. 24874   /* Check for NIL_INODE. */
  473. 24875   if (dirp == NIL_INODE) return(NIL_INODE);
  474. 24876
  475. 24877   /* If 'string' is not present in the directory, signal error. */
  476. 24878   if ( (r = search_dir(dirp, string, &numb, LOOK_UP)) != OK) {
  477. 24879         err_code = r;
  478. 24880         return(NIL_INODE);
  479. 24881   }
  480. 24882
  481. 24883   /* Don't go beyond the current root directory, unless the string is dot2. */
  482. 24884   if (dirp == fp->fp_rootdir && strcmp(string, "..") == 0 && string != dot2)
  483. 24885                 return(get_inode(dirp->i_dev, (int) dirp->i_num));
  484. 24886
  485. 24887   /* The component has been found in the directory.  Get inode. */
  486. 24888   if ( (rip = get_inode(dirp->i_dev, (int) numb)) == NIL_INODE) 
  487. 24889         return(NIL_INODE);
  488. 24890
  489. 24891   if (rip->i_num == ROOT_INODE)
  490. 24892         if (dirp->i_num == ROOT_INODE) {
  491. 24893             if (string[1] == '.') {
  492. 24894                 for (sp = &super_block[1]; sp < &super_block[NR_SUPERS]; sp++){
  493. 24895                         if (sp->s_dev == rip->i_dev) {
  494. 24896                                 /* Release the root inode.  Replace by the
  495. 24897                                  * inode mounted on.
  496. 24898                                  */
  497. 24899                                 put_inode(rip);
  498. 24900                                 mnt_dev = sp->s_imount->i_dev;
  499. 24901                                 inumb = (int) sp->s_imount->i_num;
  500. 24902                                 rip2 = get_inode(mnt_dev, inumb);
  501. 24903                                 rip = advance(rip2, string);
  502. 24904                                 put_inode(rip2);
  503. 24905                                 break;
  504. 24906                         }
  505. 24907                 }
  506. 24908             }
  507. 24909         }
  508. .Op 343 src/fs/path.c
  509. 24910   if (rip == NIL_INODE) return(NIL_INODE);
  510. 24911
  511. 24912   /* See if the inode is mounted on.  If so, switch to root directory of the
  512. 24913    * mounted file system.  The super_block provides the linkage between the
  513. 24914    * inode mounted on and the root directory of the mounted file system.
  514. 24915    */
  515. 24916   while (rip != NIL_INODE && rip->i_mount == I_MOUNT) {
  516. 24917         /* The inode is indeed mounted on. */
  517. 24918         for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++) {
  518. 24919                 if (sp->s_imount == rip) {
  519. 24920                         /* Release the inode mounted on.  Replace by the
  520. 24921                          * inode of the root inode of the mounted device.
  521. 24922                          */
  522. 24923                         put_inode(rip);
  523. 24924                         rip = get_inode(sp->s_dev, ROOT_INODE);
  524. 24925                         break;
  525. 24926                 }
  526. 24927         }
  527. 24928   }
  528. 24929   return(rip);          /* return pointer to inode's component */
  529. 24930 }
  530. 24933 /*===========================================================================*
  531. 24934  *                              search_dir                                   *
  532. 24935  *===========================================================================*/
  533. 24936 PUBLIC int search_dir(ldir_ptr, string, numb, flag)
  534. 24937 register struct inode *ldir_ptr;        /* ptr to inode for dir to search */
  535. 24938 char string[NAME_MAX];          /* component to search for */
  536. 24939 ino_t *numb;                    /* pointer to inode number */
  537. 24940 int flag;                       /* LOOK_UP, ENTER, DELETE or IS_EMPTY */
  538. 24941 {
  539. 24942 /* This function searches the directory whose inode is pointed to by 'ldip':
  540. 24943  * if (flag == ENTER)  enter 'string' in the directory with inode # '*numb';
  541. 24944  * if (flag == DELETE) delete 'string' from the directory;
  542. 24945  * if (flag == LOOK_UP) search for 'string' and return inode # in 'numb';
  543. 24946  * if (flag == IS_EMPTY) return OK if only . and .. in dir else ENOTEMPTY;
  544. 24947  *
  545. 24948  *    if 'string' is dot1 or dot2, no access permissions are checked.
  546. 24949  */
  547. 24950
  548. 24951   register struct direct *dp;
  549. 24952   register struct buf *bp;
  550. 24953   int i, r, e_hit, t, match;
  551. 24954   mode_t bits;
  552. 24955   off_t pos;
  553. 24956   unsigned new_slots, old_slots;
  554. 24957   block_t b;
  555. 24958   struct super_block *sp;
  556. 24959   int extended = 0;
  557. 24960
  558. 24961   /* If 'ldir_ptr' is not a pointer to a dir inode, error. */
  559. 24962   if ( (ldir_ptr->i_mode & I_TYPE) != I_DIRECTORY) return(ENOTDIR);
  560. 24963
  561. 24964   r = OK;
  562. 24965
  563. 24966   if (flag != IS_EMPTY) {
  564. 24967         bits = (flag == LOOK_UP ? X_BIT : W_BIT | X_BIT);
  565. 24968
  566. 24969         if (string == dot1 || string == dot2) {
  567. .Ep 344 src/fs/path.c
  568. 24970                 if (flag != LOOK_UP) r = read_only(ldir_ptr);
  569. 24971                                      /* only a writable device is required. */
  570. 24972         }
  571. 24973         else r = forbidden(ldir_ptr, bits); /* check access permissions */
  572. 24974   }
  573. 24975   if (r != OK) return(r);
  574. 24976   
  575. 24977   /* Step through the directory one block at a time. */
  576. 24978   old_slots = (unsigned) (ldir_ptr->i_size/DIR_ENTRY_SIZE);
  577. 24979   new_slots = 0;
  578. 24980   e_hit = FALSE;
  579. 24981   match = 0;                    /* set when a string match occurs */
  580. 24982
  581. 24983   for (pos = 0; pos < ldir_ptr->i_size; pos += BLOCK_SIZE) {
  582. 24984         b = read_map(ldir_ptr, pos);    /* get block number */
  583. 24985
  584. 24986         /* Since directories don't have holes, 'b' cannot be NO_BLOCK. */
  585. 24987         bp = get_block(ldir_ptr->i_dev, b, NORMAL);     /* get a dir block */
  586. 24988
  587. 24989         /* Search a directory block. */
  588. 24990         for (dp = &bp->b_dir[0]; dp < &bp->b_dir[NR_DIR_ENTRIES]; dp++) {
  589. 24991                 if (++new_slots > old_slots) { /* not found, but room left */
  590. 24992                         if (flag == ENTER) e_hit = TRUE;
  591. 24993                         break;
  592. 24994                 }
  593. 24995
  594. 24996                 /* Match occurs if string found. */
  595. 24997                 if (flag != ENTER && dp->d_ino != 0) {
  596. 24998                         if (flag == IS_EMPTY) {
  597. 24999                                 /* If this test succeeds, dir is not empty. */
  598. 25000                                 if (strcmp(dp->d_name, "." ) != 0 &&
  599. 25001                                     strcmp(dp->d_name, "..") != 0) match = 1;
  600. 25002                         } else {
  601. 25003                                 if (strncmp(dp->d_name, string, NAME_MAX) == 0)
  602. 25004                                         match = 1;
  603. 25005                         }
  604. 25006                 }
  605. 25007
  606. 25008                 if (match) {
  607. 25009                         /* LOOK_UP or DELETE found what it wanted. */
  608. 25010                         r = OK;
  609. 25011                         if (flag == IS_EMPTY) r = ENOTEMPTY;
  610. 25012                         else if (flag == DELETE) {
  611. 25013                                 /* Save d_ino for recovery. */
  612. 25014                                 t = NAME_MAX - sizeof(ino_t);
  613. 25015                                 *((ino_t *) &dp->d_name[t]) = dp->d_ino;
  614. 25016                                 dp->d_ino = 0;  /* erase entry */
  615. 25017                                 bp->b_dirt = DIRTY;
  616. 25018                                 ldir_ptr->i_update |= CTIME | MTIME;
  617. 25019                                 ldir_ptr->i_dirt = DIRTY;
  618. 25020                         } else {
  619. 25021                                 sp = ldir_ptr->i_sp;    /* 'flag' is LOOK_UP */
  620. 25022                                 *numb = conv2(sp->s_native, (int) dp->d_ino);
  621. 25023                         }
  622. 25024                         put_block(bp, DIRECTORY_BLOCK);
  623. 25025                         return(r);
  624. 25026                 }
  625. 25027
  626. 25028
  627. 25029                 /* Check for free slot for the benefit of ENTER. */
  628. .Op 345 src/fs/path.c
  629. 25030                 if (flag == ENTER && dp->d_ino == 0) {
  630. 25031                         e_hit = TRUE;   /* we found a free slot */
  631. 25032                         break;
  632. 25033                 }
  633. 25034         }
  634. 25035
  635. 25036         /* The whole block has been searched or ENTER has a free slot. */
  636. 25037         if (e_hit) break;       /* e_hit set if ENTER can be performed now */
  637. 25038         put_block(bp, DIRECTORY_BLOCK); /* otherwise, continue searching dir */
  638. 25039   }
  639. 25040
  640. 25041   /* The whole directory has now been searched. */
  641. 25042   if (flag != ENTER) return(flag == IS_EMPTY ? OK : ENOENT);
  642. 25043
  643. 25044   /* This call is for ENTER.  If no free slot has been found so far, try to
  644. 25045    * extend directory.
  645. 25046    */
  646. 25047   if (e_hit == FALSE) { /* directory is full and no room left in last block */
  647. 25048         new_slots++;            /* increase directory size by 1 entry */
  648. 25049         if (new_slots == 0) return(EFBIG); /* dir size limited by slot count */
  649. 25050         if ( (bp = new_block(ldir_ptr, ldir_ptr->i_size)) == NIL_BUF)
  650. 25051                 return(err_code);
  651. 25052         dp = &bp->b_dir[0];
  652. 25053         extended = 1;
  653. 25054   }
  654. 25055
  655. 25056   /* 'bp' now points to a directory block with space. 'dp' points to slot. */
  656. 25057   (void) memset(dp->d_name, 0, (size_t) NAME_MAX); /* clear entry */
  657. 25058   for (i = 0; string[i] && i < NAME_MAX; i++) dp->d_name[i] = string[i];
  658. 25059   sp = ldir_ptr->i_sp; 
  659. 25060   dp->d_ino = conv2(sp->s_native, (int) *numb);
  660. 25061   bp->b_dirt = DIRTY;
  661. 25062   put_block(bp, DIRECTORY_BLOCK);
  662. 25063   ldir_ptr->i_update |= CTIME | MTIME;  /* mark mtime for update later */
  663. 25064   ldir_ptr->i_dirt = DIRTY;
  664. 25065   if (new_slots > old_slots) {
  665. 25066         ldir_ptr->i_size = (off_t) new_slots * DIR_ENTRY_SIZE;
  666. 25067         /* Send the change to disk if the directory is extended. */
  667. 25068         if (extended) rw_inode(ldir_ptr, WRITING);
  668. 25069   }
  669. 25070   return(OK);
  670. 25071 }
  671. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  672. src/fs/mount.c    
  673. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  674. 25100 /* This file performs the MOUNT and UMOUNT system calls.
  675. 25101  *
  676. 25102  * The entry points into this file are
  677. 25103  *   do_mount:  perform the MOUNT system call
  678. 25104  *   do_umount: perform the UMOUNT system call
  679. 25105  */
  680. 25106
  681. 25107 #include "fs.h"
  682. 25108 #include <fcntl.h>
  683. 25109 #include <minix/com.h>
  684. .Ep 346 src/fs/mount.c
  685. 25110 #include <sys/stat.h>
  686. 25111 #include "buf.h"
  687. 25112 #include "dev.h"
  688. 25113 #include "file.h"
  689. 25114 #include "fproc.h"
  690. 25115 #include "inode.h"
  691. 25116 #include "param.h"
  692. 25117 #include "super.h"
  693. 25118
  694. 25119 PRIVATE message dev_mess;
  695. 25120
  696. 25121 FORWARD _PROTOTYPE( dev_t name_to_dev, (char *path)                     );
  697. 25122
  698. 25123 /*===========================================================================*
  699. 25124  *                              do_mount                                     *
  700. 25125  *===========================================================================*/
  701. 25126 PUBLIC int do_mount()
  702. 25127 {
  703. 25128 /* Perform the mount(name, mfile, rd_only) system call. */
  704. 25129
  705. 25130   register struct inode *rip, *root_ip;
  706. 25131   struct super_block *xp, *sp;
  707. 25132   dev_t dev;
  708. 25133   mode_t bits;
  709. 25134   int rdir, mdir;               /* TRUE iff {root|mount} file is dir */
  710. 25135   int r, found, major, task;
  711. 25136
  712. 25137   /* Only the super-user may do MOUNT. */
  713. 25138   if (!super_user) return(EPERM);
  714. 25139
  715. 25140   /* If 'name' is not for a block special file, return error. */
  716. 25141   if (fetch_name(name1, name1_length, M1) != OK) return(err_code);
  717. 25142   if ( (dev = name_to_dev(user_path)) == NO_DEV) return(err_code);
  718. 25143
  719. 25144   /* Scan super block table to see if dev already mounted & find a free slot.*/
  720. 25145   sp = NIL_SUPER;
  721. 25146   found = FALSE;
  722. 25147   for (xp = &super_block[0]; xp < &super_block[NR_SUPERS]; xp++) {
  723. 25148         if (xp->s_dev == dev) found = TRUE;     /* is it mounted already? */
  724. 25149         if (xp->s_dev == NO_DEV) sp = xp;       /* record free slot */
  725. 25150   }
  726. 25151   if (found) return(EBUSY);     /* already mounted */
  727. 25152   if (sp == NIL_SUPER) return(ENFILE);  /* no super block available */
  728. 25153
  729. 25154   dev_mess.m_type = DEV_OPEN;           /* distinguish from close */
  730. 25155   dev_mess.DEVICE = dev;                /* Touch the device. */  
  731. 25156   if (rd_only) dev_mess.COUNT = R_BIT;
  732. 25157   else  dev_mess.COUNT = R_BIT|W_BIT;
  733. 25158
  734. 25159   major = (dev >> MAJOR) & BYTE;
  735. 25160   if (major <= 0 || major >= max_major) return(ENODEV);
  736. 25161   task = dmap[major].dmap_task;         /* device task nr */
  737. 25162   (*dmap[major].dmap_open)(task, &dev_mess);
  738. 25163   if (dev_mess.REP_STATUS != OK) return(EINVAL);
  739. 25164
  740. 25165   /* Fill in the super block. */
  741. 25166   sp->s_dev = dev;              /* read_super() needs to know which dev */
  742. 25167   r = read_super(sp);
  743. 25168
  744. 25169   /* Is it recognized as a Minix filesystem? */
  745. .Op 347 src/fs/mount.c
  746. 25170   if (r != OK) {
  747. 25171         dev_mess.m_type = DEV_CLOSE;
  748. 25172         dev_mess.DEVICE = dev;
  749. 25173         (*dmap[major].dmap_close)(task, &dev_mess);
  750. 25174         return(r);
  751. 25175   }
  752. 25176
  753. 25177   /* Now get the inode of the file to be mounted on. */
  754. 25178   if (fetch_name(name2, name2_length, M1) != OK) {
  755. 25179         sp->s_dev = NO_DEV;
  756. 25180         dev_mess.m_type = DEV_CLOSE;
  757. 25181         dev_mess.DEVICE = dev;
  758. 25182         (*dmap[major].dmap_close)(task, &dev_mess);
  759. 25183         return(err_code);
  760. 25184   }
  761. 25185   if ( (rip = eat_path(user_path)) == NIL_INODE) {
  762. 25186         sp->s_dev = NO_DEV;
  763. 25187         dev_mess.m_type = DEV_CLOSE;
  764. 25188         dev_mess.DEVICE = dev;
  765. 25189         (*dmap[major].dmap_close)(task, &dev_mess);
  766. 25190         return(err_code);
  767. 25191   }
  768. 25192
  769. 25193   /* It may not be busy. */
  770. 25194   r = OK;
  771. 25195   if (rip->i_count > 1) r = EBUSY;
  772. 25196
  773. 25197   /* It may not be special. */
  774. 25198   bits = rip->i_mode & I_TYPE;
  775. 25199   if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL) r = ENOTDIR;
  776. 25200
  777. 25201   /* Get the root inode of the mounted file system. */
  778. 25202   root_ip = NIL_INODE;          /* if 'r' not OK, make sure this is defined */
  779. 25203   if (r == OK) {
  780. 25204         if ( (root_ip = get_inode(dev, ROOT_INODE)) == NIL_INODE) r = err_code;
  781. 25205   }
  782. 25206   if (root_ip != NIL_INODE && root_ip->i_mode == 0) r = EINVAL;
  783. 25207
  784. 25208   /* File types of 'rip' and 'root_ip' may not conflict. */
  785. 25209   if (r == OK) {
  786. 25210         mdir = ((rip->i_mode & I_TYPE) == I_DIRECTORY);  /* TRUE iff dir */
  787. 25211         rdir = ((root_ip->i_mode & I_TYPE) == I_DIRECTORY);
  788. 25212         if (!mdir && rdir) r = EISDIR;
  789. 25213   }
  790. 25214
  791. 25215   /* If error, return the super block and both inodes; release the maps. */
  792. 25216   if (r != OK) {
  793. 25217         put_inode(rip);
  794. 25218         put_inode(root_ip);
  795. 25219         (void) do_sync();
  796. 25220         invalidate(dev);
  797. 25221
  798. 25222         sp->s_dev = NO_DEV;
  799. 25223         dev_mess.m_type = DEV_CLOSE;
  800. 25224         dev_mess.DEVICE = dev;
  801. 25225         (*dmap[major].dmap_close)(task, &dev_mess);
  802. 25226         return(r);
  803. 25227   }
  804. 25228
  805. 25229   /* Nothing else can go wrong.  Perform the mount. */
  806. .Ep 348 src/fs/mount.c
  807. 25230   rip->i_mount = I_MOUNT;       /* this bit says the inode is mounted on */
  808. 25231   sp->s_imount = rip;
  809. 25232   sp->s_isup = root_ip;
  810. 25233   sp->s_rd_only = rd_only;
  811. 25234   return(OK);
  812. 25235 }
  813. 25238 /*===========================================================================*
  814. 25239  *                              do_umount                                    *
  815. 25240  *===========================================================================*/
  816. 25241 PUBLIC int do_umount()
  817. 25242 {
  818. 25243 /* Perform the umount(name) system call. */
  819. 25244
  820. 25245   register struct inode *rip;
  821. 25246   struct super_block *sp, *sp1;
  822. 25247   dev_t dev;
  823. 25248   int count;
  824. 25249   int major, task;
  825. 25250
  826. 25251   /* Only the super-user may do UMOUNT. */
  827. 25252   if (!super_user) return(EPERM);
  828. 25253
  829. 25254   /* If 'name' is not for a block special file, return error. */
  830. 25255   if (fetch_name(name, name_length, M3) != OK) return(err_code);
  831. 25256   if ( (dev = name_to_dev(user_path)) == NO_DEV) return(err_code);
  832. 25257
  833. 25258   /* See if the mounted device is busy.  Only 1 inode using it should be
  834. 25259    * open -- the root inode -- and that inode only 1 time.
  835. 25260    */
  836. 25261   count = 0;
  837. 25262   for (rip = &inode[0]; rip< &inode[NR_INODES]; rip++)
  838. 25263         if (rip->i_count > 0 && rip->i_dev == dev) count += rip->i_count;
  839. 25264   if (count > 1) return(EBUSY); /* can't umount a busy file system */
  840. 25265
  841. 25266   /* Find the super block. */
  842. 25267   sp = NIL_SUPER;
  843. 25268   for (sp1 = &super_block[0]; sp1 < &super_block[NR_SUPERS]; sp1++) {
  844. 25269         if (sp1->s_dev == dev) {
  845. 25270                 sp = sp1;
  846. 25271                 break;
  847. 25272         }
  848. 25273   }
  849. 25274
  850. 25275   /* Sync the disk, and invalidate cache. */
  851. 25276   (void) do_sync();             /* force any cached blocks out of memory */
  852. 25277   invalidate(dev);              /* invalidate cache entries for this dev */
  853. 25278   if (sp == NIL_SUPER) return(EINVAL);
  854. 25279
  855. 25280   major = (dev >> MAJOR) & BYTE;        /* major device nr */
  856. 25281   task = dmap[major].dmap_task; /* device task nr */
  857. 25282   dev_mess.m_type = DEV_CLOSE;          /* distinguish from open */
  858. 25283   dev_mess.DEVICE = dev;
  859. 25284   (*dmap[major].dmap_close)(task, &dev_mess);
  860. 25285
  861. 25286   /* Finish off the unmount. */
  862. 25287   sp->s_imount->i_mount = NO_MOUNT;     /* inode returns to normal */
  863. 25288   put_inode(sp->s_imount);      /* release the inode mounted on */
  864. 25289   put_inode(sp->s_isup);        /* release the root inode of the mounted fs */
  865. .Op 349 src/fs/mount.c
  866. 25290   sp->s_imount = NIL_INODE;
  867. 25291   sp->s_dev = NO_DEV;
  868. 25292   return(OK);
  869. 25293 }
  870. 25296 /*===========================================================================*
  871. 25297  *                              name_to_dev                                  *
  872. 25298  *===========================================================================*/
  873. 25299 PRIVATE dev_t name_to_dev(path)
  874. 25300 char *path;                     /* pointer to path name */
  875. 25301 {
  876. 25302 /* Convert the block special file 'path' to a device number.  If 'path'
  877. 25303  * is not a block special file, return error code in 'err_code'.
  878. 25304  */
  879. 25305
  880. 25306   register struct inode *rip;
  881. 25307   register dev_t dev;
  882. 25308
  883. 25309   /* If 'path' can't be opened, give up immediately. */
  884. 25310   if ( (rip = eat_path(path)) == NIL_INODE) return(NO_DEV);
  885. 25311
  886. 25312   /* If 'path' is not a block special file, return error. */
  887. 25313   if ( (rip->i_mode & I_TYPE) != I_BLOCK_SPECIAL) {
  888. 25314         err_code = ENOTBLK;
  889. 25315         put_inode(rip);
  890. 25316         return(NO_DEV);
  891. 25317   }
  892. 25318
  893. 25319   /* Extract the device number. */
  894. 25320   dev = (dev_t) rip->i_zone[0];
  895. 25321   put_inode(rip);
  896. 25322   return(dev);
  897. 25323 }
  898. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  899. src/fs/link.c    
  900. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  901. 25400 /* This file handles the LINK and UNLINK system calls.  It also deals with
  902. 25401  * deallocating the storage used by a file when the last UNLINK is done to a
  903. 25402  * file and the blocks must be returned to the free block pool.
  904. 25403  *
  905. 25404  * The entry points into this file are
  906. 25405  *   do_link:   perform the LINK system call
  907. 25406  *   do_unlink: perform the UNLINK and RMDIR system calls
  908. 25407  *   do_rename: perform the RENAME system call
  909. 25408  *   truncate:  release all the blocks associated with an inode
  910. 25409  */
  911. 25410
  912. 25411 #include "fs.h"
  913. 25412 #include <sys/stat.h>
  914. 25413 #include <string.h>
  915. 25414 #include <minix/callnr.h>
  916. 25415 #include "buf.h"
  917. 25416 #include "file.h"
  918. 25417 #include "fproc.h"
  919. 25418 #include "inode.h"
  920. 25419 #include "param.h"
  921. .Ep 350 src/fs/link.c
  922. 25420 #include "super.h"
  923. 25421
  924. 25422 #define SAME 1000
  925. 25423
  926. 25424 FORWARD _PROTOTYPE( int remove_dir, (struct inode *rldirp, struct inode *rip,
  927. 25425                         char dir_name[NAME_MAX])                        );
  928. 25426
  929. 25427 FORWARD _PROTOTYPE( int unlink_file, (struct inode *dirp, struct inode *rip,
  930. 25428                         char file_name[NAME_MAX])                       );
  931. 25429
  932. 25430
  933. 25431 /*===========================================================================*
  934. 25432  *                              do_link                                      *
  935. 25433  *===========================================================================*/
  936. 25434 PUBLIC int do_link()
  937. 25435 {
  938. 25436 /* Perform the link(name1, name2) system call. */
  939. 25437
  940. 25438   register struct inode *ip, *rip;
  941. 25439   register int r;
  942. 25440   char string[NAME_MAX];
  943. 25441   struct inode *new_ip;
  944. 25442
  945. 25443   /* See if 'name' (file to be linked) exists. */
  946. 25444   if (fetch_name(name1, name1_length, M1) != OK) return(err_code);
  947. 25445   if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
  948. 25446
  949. 25447   /* Check to see if the file has maximum number of links already. */
  950. 25448   r = OK;
  951. 25449   if ( (rip->i_nlinks & BYTE) >= LINK_MAX) r = EMLINK;
  952. 25450
  953. 25451   /* Only super_user may link to directories. */
  954. 25452   if (r == OK)
  955. 25453         if ( (rip->i_mode & I_TYPE) == I_DIRECTORY && !super_user) r = EPERM;
  956. 25454
  957. 25455   /* If error with 'name', return the inode. */
  958. 25456   if (r != OK) {
  959. 25457         put_inode(rip);
  960. 25458         return(r);
  961. 25459   }
  962. 25460
  963. 25461   /* Does the final directory of 'name2' exist? */
  964. 25462   if (fetch_name(name2, name2_length, M1) != OK) {
  965. 25463         put_inode(rip);
  966. 25464         return(err_code);
  967. 25465   }
  968. 25466   if ( (ip = last_dir(user_path, string)) == NIL_INODE) r = err_code;
  969. 25467
  970. 25468   /* If 'name2' exists in full (even if no space) set 'r' to error. */
  971. 25469   if (r == OK) {
  972. 25470         if ( (new_ip = advance(ip, string)) == NIL_INODE) {
  973. 25471                 r = err_code;
  974. 25472                 if (r == ENOENT) r = OK;
  975. 25473         } else {
  976. 25474                 put_inode(new_ip);
  977. 25475                 r = EEXIST;
  978. 25476         }
  979. 25477   }
  980. 25478
  981. 25479   /* Check for links across devices. */
  982. .Op 351 src/fs/link.c
  983. 25480   if (r == OK)
  984. 25481         if (rip->i_dev != ip->i_dev) r = EXDEV;
  985. 25482
  986. 25483   /* Try to link. */
  987. 25484   if (r == OK)
  988. 25485         r = search_dir(ip, string, &rip->i_num, ENTER);
  989. 25486
  990. 25487   /* If success, register the linking. */
  991. 25488   if (r == OK) {
  992. 25489         rip->i_nlinks++;
  993. 25490         rip->i_update |= CTIME;
  994. 25491         rip->i_dirt = DIRTY;
  995. 25492   }
  996. 25493
  997. 25494   /* Done.  Release both inodes. */
  998. 25495   put_inode(rip);
  999. 25496   put_inode(ip);
  1000. 25497   return(r);
  1001. 25498 }
  1002. 25501 /*===========================================================================*
  1003. 25502  *                              do_unlink                                    *
  1004. 25503  *===========================================================================*/
  1005. 25504 PUBLIC int do_unlink()
  1006. 25505 {
  1007. 25506 /* Perform the unlink(name) or rmdir(name) system call. The code for these two
  1008. 25507  * is almost the same.  They differ only in some condition testing.  Unlink()
  1009. 25508  * may be used by the superuser to do dangerous things; rmdir() may not.
  1010. 25509  */
  1011. 25510
  1012. 25511   register struct inode *rip;
  1013. 25512   struct inode *rldirp;
  1014. 25513   int r;
  1015. 25514   char string[NAME_MAX];
  1016. 25515
  1017. 25516   /* Get the last directory in the path. */
  1018. 25517   if (fetch_name(name, name_length, M3) != OK) return(err_code);
  1019. 25518   if ( (rldirp = last_dir(user_path, string)) == NIL_INODE)
  1020. 25519         return(err_code);
  1021. 25520
  1022. 25521   /* The last directory exists.  Does the file also exist? */
  1023. 25522   r = OK;
  1024. 25523   if ( (rip = advance(rldirp, string)) == NIL_INODE) r = err_code;
  1025. 25524
  1026. 25525   /* If error, return inode. */
  1027. 25526   if (r != OK) {
  1028. 25527         put_inode(rldirp);
  1029. 25528         return(r);
  1030. 25529   }
  1031. 25530
  1032. 25531   /* Do not remove a mount point. */
  1033. 25532   if (rip->i_num == ROOT_INODE) {
  1034. 25533         put_inode(rldirp);
  1035. 25534         put_inode(rip);
  1036. 25535         return(EBUSY);
  1037. 25536   }
  1038. 25537
  1039. 25538   /* Now test if the call is allowed, separately for unlink() and rmdir(). */
  1040. 25539   if (fs_call == UNLINK) {
  1041. .Ep 352 src/fs/link.c
  1042. 25540         /* Only the su may unlink directories, but the su can unlink any dir.*/
  1043. 25541         if ( (rip->i_mode & I_TYPE) == I_DIRECTORY && !super_user) r = EPERM;
  1044. 25542
  1045. 25543         /* Don't unlink a file if it is the root of a mounted file system. */
  1046. 25544         if (rip->i_num == ROOT_INODE) r = EBUSY;
  1047. 25545
  1048. 25546         /* Actually try to unlink the file; fails if parent is mode 0 etc. */
  1049. 25547         if (r == OK) r = unlink_file(rldirp, rip, string);
  1050. 25548
  1051. 25549   } else {
  1052. 25550         r = remove_dir(rldirp, rip, string); /* call is RMDIR */
  1053. 25551   }
  1054. 25552
  1055. 25553   /* If unlink was possible, it has been done, otherwise it has not. */
  1056. 25554   put_inode(rip);
  1057. 25555   put_inode(rldirp);
  1058. 25556   return(r);
  1059. 25557 }
  1060. 25560 /*===========================================================================*
  1061. 25561  *                              do_rename                                    *
  1062. 25562  *===========================================================================*/
  1063. 25563 PUBLIC int do_rename()
  1064. 25564 {
  1065. 25565 /* Perform the rename(name1, name2) system call. */
  1066. 25566
  1067. 25567   struct inode *old_dirp, *old_ip;      /* ptrs to old dir, file inodes */
  1068. 25568   struct inode *new_dirp, *new_ip;      /* ptrs to new dir, file inodes */
  1069. 25569   struct inode *new_superdirp, *next_new_superdirp;
  1070. 25570   int r = OK;                           /* error flag; initially no error */
  1071. 25571   int odir, ndir;                       /* TRUE iff {old|new} file is dir */
  1072. 25572   int same_pdir;                        /* TRUE iff parent dirs are the same */
  1073. 25573   char old_name[NAME_MAX], new_name[NAME_MAX];
  1074. 25574   ino_t numb;
  1075. 25575   int r1;
  1076. 25576   
  1077. 25577   /* See if 'name1' (existing file) exists.  Get dir and file inodes. */
  1078. 25578   if (fetch_name(name1, name1_length, M1) != OK) return(err_code);
  1079. 25579   if ( (old_dirp = last_dir(user_path, old_name))==NIL_INODE) return(err_code);
  1080. 25580
  1081. 25581   if ( (old_ip = advance(old_dirp, old_name)) == NIL_INODE) r = err_code;
  1082. 25582
  1083. 25583   /* See if 'name2' (new name) exists.  Get dir and file inodes. */
  1084. 25584   if (fetch_name(name2, name2_length, M1) != OK) r = err_code;
  1085. 25585   if ( (new_dirp = last_dir(user_path, new_name)) == NIL_INODE) r = err_code;
  1086. 25586   new_ip = advance(new_dirp, new_name); /* not required to exist */
  1087. 25587
  1088. 25588   if (old_ip != NIL_INODE)
  1089. 25589         odir = ((old_ip->i_mode & I_TYPE) == I_DIRECTORY);  /* TRUE iff dir */
  1090. 25590
  1091. 25591   /* If it is ok, check for a variety of possible errors. */
  1092. 25592   if (r == OK) {
  1093. 25593         same_pdir = (old_dirp == new_dirp);
  1094. 25594
  1095. 25595         /* The old inode must not be a superdirectory of the new last dir. */
  1096. 25596         if (odir && !same_pdir) {
  1097. 25597                 dup_inode(new_superdirp = new_dirp);
  1098. 25598                 while (TRUE) {          /* may hang in a file system loop */
  1099. 25599                         if (new_superdirp == old_ip) {
  1100. .Op 353 src/fs/link.c
  1101. 25600                                 r = EINVAL;
  1102. 25601                                 break;
  1103. 25602                         }
  1104. 25603                         next_new_superdirp = advance(new_superdirp, dot2);
  1105. 25604                         put_inode(new_superdirp);
  1106. 25605                         if (next_new_superdirp == new_superdirp)
  1107. 25606                                 break;  /* back at system root directory */
  1108. 25607                         new_superdirp = next_new_superdirp;
  1109. 25608                         if (new_superdirp == NIL_INODE) {
  1110. 25609                                 /* Missing ".." entry.  Assume the worst. */
  1111. 25610                                 r = EINVAL;
  1112. 25611                                 break;
  1113. 25612                         }
  1114. 25613                 }       
  1115. 25614                 put_inode(new_superdirp);
  1116. 25615         }       
  1117. 25616
  1118. 25617         /* The old or new name must not be . or .. */
  1119. 25618         if (strcmp(old_name, ".")==0 || strcmp(old_name, "..")==0 ||
  1120. 25619             strcmp(new_name, ".")==0 || strcmp(new_name, "..")==0) r = EINVAL;
  1121. 25620
  1122. 25621         /* Both parent directories must be on the same device. */
  1123. 25622         if (old_dirp->i_dev != new_dirp->i_dev) r = EXDEV;
  1124. 25623
  1125. 25624         /* Parent dirs must be writable, searchable and on a writable device */
  1126. 25625         if ((r1 = forbidden(old_dirp, W_BIT | X_BIT)) != OK ||
  1127. 25626             (r1 = forbidden(new_dirp, W_BIT | X_BIT)) != OK) r = r1;
  1128. 25627
  1129. 25628         /* Some tests apply only if the new path exists. */
  1130. 25629         if (new_ip == NIL_INODE) {
  1131. 25630                 /* don't rename a file with a file system mounted on it. */
  1132. 25631                 if (old_ip->i_dev != old_dirp->i_dev) r = EXDEV;
  1133. 25632                 if (odir && (new_dirp->i_nlinks & BYTE) >= LINK_MAX &&
  1134. 25633                     !same_pdir && r == OK) r = EMLINK;
  1135. 25634         } else {
  1136. 25635                 if (old_ip == new_ip) r = SAME; /* old=new */
  1137. 25636
  1138. 25637                 /* has the old file or new file a file system mounted on it? */
  1139. 25638                 if (old_ip->i_dev != new_ip->i_dev) r = EXDEV;
  1140. 25639
  1141. 25640                 ndir = ((new_ip->i_mode & I_TYPE) == I_DIRECTORY); /* dir ? */
  1142. 25641                 if (odir == TRUE && ndir == FALSE) r = ENOTDIR;
  1143. 25642                 if (odir == FALSE && ndir == TRUE) r = EISDIR;
  1144. 25643         }
  1145. 25644   }
  1146. 25645
  1147. 25646   /* If a process has another root directory than the system root, we might
  1148. 25647    * "accidently" be moving it's working directory to a place where it's
  1149. 25648    * root directory isn't a super directory of it anymore. This can make
  1150. 25649    * the function chroot useless. If chroot will be used often we should
  1151. 25650    * probably check for it here.
  1152. 25651    */
  1153. 25652
  1154. 25653   /* The rename will probably work. Only two things can go wrong now:
  1155. 25654    * 1. being unable to remove the new file. (when new file already exists)
  1156. 25655    * 2. being unable to make the new directory entry. (new file doesn't exists)
  1157. 25656    *     [directory has to grow by one block and cannot because the disk
  1158. 25657    *      is completely full].
  1159. 25658    */
  1160. 25659   if (r == OK) {
  1161. .Ep 354 src/fs/link.c
  1162. 25660         if (new_ip != NIL_INODE) {
  1163. 25661                   /* There is already an entry for 'new'. Try to remove it. */
  1164. 25662                 if (odir) 
  1165. 25663                         r = remove_dir(new_dirp, new_ip, new_name);
  1166. 25664                 else 
  1167. 25665                         r = unlink_file(new_dirp, new_ip, new_name);
  1168. 25666         }
  1169. 25667         /* if r is OK, the rename will succeed, while there is now an
  1170. 25668          * unused entry in the new parent directory.
  1171. 25669          */
  1172. 25670   }
  1173. 25671
  1174. 25672   if (r == OK) {
  1175. 25673         /* If the new name will be in the same parent directory as the old one,
  1176. 25674          * first remove the old name to free an entry for the new name,
  1177. 25675          * otherwise first try to create the new name entry to make sure
  1178. 25676          * the rename will succeed.
  1179. 25677          */
  1180. 25678         numb = old_ip->i_num;           /* inode number of old file */
  1181. 25679
  1182. 25680         if (same_pdir) {
  1183. 25681                 r = search_dir(old_dirp, old_name, (ino_t *) 0, DELETE);
  1184. 25682                                                 /* shouldn't go wrong. */
  1185. 25683                 if (r==OK) (void) search_dir(old_dirp, new_name, &numb, ENTER);
  1186. 25684         } else {
  1187. 25685                 r = search_dir(new_dirp, new_name, &numb, ENTER);
  1188. 25686                 if (r == OK)
  1189. 25687                     (void) search_dir(old_dirp, old_name, (ino_t *) 0, DELETE);
  1190. 25688         }
  1191. 25689   }
  1192. 25690   /* If r is OK, the ctime and mtime of old_dirp and new_dirp have been marked
  1193. 25691    * for update in search_dir.
  1194. 25692    */
  1195. 25693
  1196. 25694   if (r == OK && odir && !same_pdir) {
  1197. 25695         /* Update the .. entry in the directory (still points to old_dirp). */
  1198. 25696         numb = new_dirp->i_num;
  1199. 25697         (void) unlink_file(old_ip, NIL_INODE, dot2);
  1200. 25698         if (search_dir(old_ip, dot2, &numb, ENTER) == OK) {
  1201. 25699                 /* New link created. */
  1202. 25700                 new_dirp->i_nlinks++;
  1203. 25701                 new_dirp->i_dirt = DIRTY;
  1204. 25702         }
  1205. 25703   }
  1206. 25704         
  1207. 25705   /* Release the inodes. */
  1208. 25706   put_inode(old_dirp);
  1209. 25707   put_inode(old_ip);
  1210. 25708   put_inode(new_dirp);
  1211. 25709   put_inode(new_ip);
  1212. 25710   return(r == SAME ? OK : r);
  1213. 25711 }
  1214. 25714 /*===========================================================================*
  1215. 25715  *                              truncate                                     *
  1216. 25716  *===========================================================================*/
  1217. 25717 PUBLIC void truncate(rip)
  1218. 25718 register struct inode *rip;     /* pointer to inode to be truncated */
  1219. 25719 {
  1220. .Op 355 src/fs/link.c
  1221. 25720 /* Remove all the zones from the inode 'rip' and mark it dirty. */
  1222. 25721
  1223. 25722   register block_t b;
  1224. 25723   zone_t z, zone_size, z1;
  1225. 25724   off_t position;
  1226. 25725   int i, scale, file_type, waspipe, single, nr_indirects;
  1227. 25726   struct buf *bp;
  1228. 25727   dev_t dev;
  1229. 25728
  1230. 25729   file_type = rip->i_mode & I_TYPE;     /* check to see if file is special */
  1231. 25730   if (file_type == I_CHAR_SPECIAL || file_type == I_BLOCK_SPECIAL) return;
  1232. 25731   dev = rip->i_dev;             /* device on which inode resides */
  1233. 25732   scale = rip->i_sp->s_log_zone_size;
  1234. 25733   zone_size = (zone_t) BLOCK_SIZE << scale;
  1235. 25734   nr_indirects = rip->i_nindirs;
  1236. 25735
  1237. 25736   /* Pipes can shrink, so adjust size to make sure all zones are removed. */
  1238. 25737   waspipe = rip->i_pipe == I_PIPE;      /* TRUE is this was a pipe */
  1239. 25738   if (waspipe) rip->i_size = PIPE_SIZE;
  1240. 25739
  1241. 25740   /* Step through the file a zone at a time, finding and freeing the zones. */
  1242. 25741   for (position = 0; position < rip->i_size; position += zone_size) {
  1243. 25742         if ( (b = read_map(rip, position)) != NO_BLOCK) {
  1244. 25743                 z = (zone_t) b >> scale;
  1245. 25744                 free_zone(dev, z);
  1246. 25745         }
  1247. 25746   }
  1248. 25747
  1249. 25748   /* All the data zones have been freed.  Now free the indirect zones. */
  1250. 25749   rip->i_dirt = DIRTY;
  1251. 25750   if (waspipe) {
  1252. 25751         wipe_inode(rip);        /* clear out inode for pipes */
  1253. 25752         return;                 /* indirect slots contain file positions */
  1254. 25753   }
  1255. 25754   single = rip->i_ndzones;
  1256. 25755   free_zone(dev, rip->i_zone[single]);  /* single indirect zone */
  1257. 25756   if ( (z = rip->i_zone[single+1]) != NO_ZONE) {
  1258. 25757         /* Free all the single indirect zones pointed to by the double. */
  1259. 25758         b = (block_t) z << scale;
  1260. 25759         bp = get_block(dev, b, NORMAL); /* get double indirect zone */
  1261. 25760         for (i = 0; i < nr_indirects; i++) {
  1262. 25761                 z1 = rd_indir(bp, i);
  1263. 25762                 free_zone(dev, z1);
  1264. 25763         }
  1265. 25764
  1266. 25765         /* Now free the double indirect zone itself. */
  1267. 25766         put_block(bp, INDIRECT_BLOCK);
  1268. 25767         free_zone(dev, z);
  1269. 25768   }
  1270. 25769
  1271. 25770   /* Leave zone numbers for de(1) to recover file after an unlink(2).  */
  1272. 25771 }
  1273. 25774 /*===========================================================================*
  1274. 25775  *                              remove_dir                                   *
  1275. 25776  *===========================================================================*/
  1276. 25777 PRIVATE int remove_dir(rldirp, rip, dir_name)
  1277. 25778 struct inode *rldirp;                   /* parent directory */
  1278. 25779 struct inode *rip;                      /* directory to be removed */
  1279. .Ep 356 src/fs/link.c
  1280. 25780 char dir_name[NAME_MAX];                /* name of directory to be removed */
  1281. 25781 {
  1282. 25782   /* A directory file has to be removed. Five conditions have to met:
  1283. 25783    *    - The file must be a directory
  1284. 25784    *    - The directory must be empty (except for . and ..)
  1285. 25785    *    - The final component of the path must not be . or ..
  1286. 25786    *    - The directory must not be the root of a mounted file system
  1287. 25787    *    - The directory must not be anybody's root/working directory
  1288. 25788    */
  1289. 25789
  1290. 25790   int r;
  1291. 25791   register struct fproc *rfp;
  1292. 25792
  1293. 25793   /* search_dir checks that rip is a directory too. */
  1294. 25794   if ((r = search_dir(rip, "", (ino_t *) 0, IS_EMPTY)) != OK) return r;
  1295. 25795
  1296. 25796   if (strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0)return(EINVAL);
  1297. 25797   if (rip->i_num == ROOT_INODE) return(EBUSY); /* can't remove 'root' */
  1298. 25798   
  1299. 25799   for (rfp = &fproc[INIT_PROC_NR + 1]; rfp < &fproc[NR_PROCS]; rfp++)
  1300. 25800         if (rfp->fp_workdir == rip || rfp->fp_rootdir == rip) return(EBUSY);
  1301. 25801                                 /* can't remove anybody's working dir */
  1302. 25802
  1303. 25803   /* Actually try to unlink the file; fails if parent is mode 0 etc. */
  1304. 25804   if ((r = unlink_file(rldirp, rip, dir_name)) != OK) return r;
  1305. 25805
  1306. 25806   /* Unlink . and .. from the dir. The super user can link and unlink any dir,
  1307. 25807    * so don't make too many assumptions about them.
  1308. 25808    */
  1309. 25809   (void) unlink_file(rip, NIL_INODE, dot1);
  1310. 25810   (void) unlink_file(rip, NIL_INODE, dot2);
  1311. 25811   return(OK);
  1312. 25812 }
  1313. 25815 /*===========================================================================*
  1314. 25816  *                              unlink_file                                  *
  1315. 25817  *===========================================================================*/
  1316. 25818 PRIVATE int unlink_file(dirp, rip, file_name)
  1317. 25819 struct inode *dirp;             /* parent directory of file */
  1318. 25820 struct inode *rip;              /* inode of file, may be NIL_INODE too. */
  1319. 25821 char file_name[NAME_MAX];       /* name of file to be removed */
  1320. 25822 {
  1321. 25823 /* Unlink 'file_name'; rip must be the inode of 'file_name' or NIL_INODE. */
  1322. 25824
  1323. 25825   ino_t numb;                   /* inode number */
  1324. 25826   int   r;
  1325. 25827
  1326. 25828   /* If rip is not NIL_INODE, it is used to get faster access to the inode. */
  1327. 25829   if (rip == NIL_INODE) {
  1328. 25830         /* Search for file in directory and try to get its inode. */
  1329. 25831         err_code = search_dir(dirp, file_name, &numb, LOOK_UP);
  1330. 25832         if (err_code == OK) rip = get_inode(dirp->i_dev, (int) numb);
  1331. 25833         if (err_code != OK || rip == NIL_INODE) return(err_code);
  1332. 25834   } else {
  1333. 25835         dup_inode(rip);         /* inode will be returned with put_inode */
  1334. 25836   }
  1335. 25837
  1336. 25838   r = search_dir(dirp, file_name, (ino_t *) 0, DELETE);
  1337. 25839
  1338. .Op 357 src/fs/link.c
  1339. 25840   if (r == OK) {
  1340. 25841         rip->i_nlinks--;        /* entry deleted from parent's dir */
  1341. 25842         rip->i_update |= CTIME;
  1342. 25843         rip->i_dirt = DIRTY;
  1343. 25844   }
  1344. 25845
  1345. 25846   put_inode(rip);
  1346. 25847   return(r);
  1347. 25848 }
  1348. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1349. src/fs/stadir.c    
  1350. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1351. 25900 /* This file contains the code for performing four system calls relating to
  1352. 25901  * status and directories.
  1353. 25902  *
  1354. 25903  * The entry points into this file are
  1355. 25904  *   do_chdir:  perform the CHDIR system call
  1356. 25905  *   do_chroot: perform the CHROOT system call
  1357. 25906  *   do_stat:   perform the STAT system call
  1358. 25907  *   do_fstat:  perform the FSTAT system call
  1359. 25908  */
  1360. 25909
  1361. 25910 #include "fs.h"
  1362. 25911 #include <sys/stat.h>
  1363. 25912 #include "file.h"
  1364. 25913 #include "fproc.h"
  1365. 25914 #include "inode.h"
  1366. 25915 #include "param.h"
  1367. 25916
  1368. 25917 FORWARD _PROTOTYPE( int change, (struct inode **iip, char *name_ptr, int len));
  1369. 25918 FORWARD _PROTOTYPE( int stat_inode, (struct inode *rip, struct filp *fil_ptr,
  1370. 25919                         char *user_addr)                                );
  1371. 25920
  1372. 25921 /*===========================================================================*
  1373. 25922  *                              do_chdir                                     *
  1374. 25923  *===========================================================================*/
  1375. 25924 PUBLIC int do_chdir()
  1376. 25925 {
  1377. 25926 /* Change directory.  This function is  also called by MM to simulate a chdir
  1378. 25927  * in order to do EXEC, etc.  It also changes the root directory, the uids and
  1379. 25928  * gids, and the umask. 
  1380. 25929  */
  1381. 25930
  1382. 25931   int r;
  1383. 25932   register struct fproc *rfp;
  1384. 25933
  1385. 25934   if (who == MM_PROC_NR) {
  1386. 25935         rfp = &fproc[slot1];
  1387. 25936         put_inode(fp->fp_rootdir);
  1388. 25937         dup_inode(fp->fp_rootdir = rfp->fp_rootdir);
  1389. 25938         put_inode(fp->fp_workdir);
  1390. 25939         dup_inode(fp->fp_workdir = rfp->fp_workdir);
  1391. 25940
  1392. 25941         /* MM uses access() to check permissions.  To make this work, pretend
  1393. 25942          * that the user's real ids are the same as the user's effective ids.
  1394. 25943          * FS calls other than access() do not use the real ids, so are not
  1395. 25944          * affected.
  1396. .Ep 358 src/fs/stadir.c
  1397. 25945          */
  1398. 25946         fp->fp_realuid =
  1399. 25947         fp->fp_effuid = rfp->fp_effuid;
  1400. 25948         fp->fp_realgid =
  1401. 25949         fp->fp_effgid = rfp->fp_effgid;
  1402. 25950         fp->fp_umask = rfp->fp_umask;
  1403. 25951         return(OK);
  1404. 25952   }
  1405. 25953
  1406. 25954   /* Perform the chdir(name) system call. */
  1407. 25955   r = change(&fp->fp_workdir, name, name_length);
  1408. 25956   return(r);
  1409. 25957 }
  1410. 25960 /*===========================================================================*
  1411. 25961  *                              do_chroot                                    *
  1412. 25962  *===========================================================================*/
  1413. 25963 PUBLIC int do_chroot()
  1414. 25964 {
  1415. 25965 /* Perform the chroot(name) system call. */
  1416. 25966
  1417. 25967   register int r;
  1418. 25968
  1419. 25969   if (!super_user) return(EPERM);       /* only su may chroot() */
  1420. 25970   r = change(&fp->fp_rootdir, name, name_length);
  1421. 25971   return(r);
  1422. 25972 }
  1423. 25975 /*===========================================================================*
  1424. 25976  *                              change                                       *
  1425. 25977  *===========================================================================*/
  1426. 25978 PRIVATE int change(iip, name_ptr, len)
  1427. 25979 struct inode **iip;             /* pointer to the inode pointer for the dir */
  1428. 25980 char *name_ptr;                 /* pointer to the directory name to change to */
  1429. 25981 int len;                        /* length of the directory name string */
  1430. 25982 {
  1431. 25983 /* Do the actual work for chdir() and chroot(). */
  1432. 25984
  1433. 25985   struct inode *rip;
  1434. 25986   register int r;
  1435. 25987
  1436. 25988   /* Try to open the new directory. */
  1437. 25989   if (fetch_name(name_ptr, len, M3) != OK) return(err_code);
  1438. 25990   if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
  1439. 25991
  1440. 25992   /* It must be a directory and also be searchable. */
  1441. 25993   if ( (rip->i_mode & I_TYPE) != I_DIRECTORY)
  1442. 25994         r = ENOTDIR;
  1443. 25995   else
  1444. 25996         r = forbidden(rip, X_BIT);      /* check if dir is searchable */
  1445. 25997
  1446. 25998   /* If error, return inode. */
  1447. 25999   if (r != OK) {
  1448. 26000         put_inode(rip);
  1449. 26001         return(r);
  1450. 26002   }
  1451. 26003
  1452. 26004   /* Everything is OK.  Make the change. */
  1453. .Op 359 src/fs/stadir.c
  1454. 26005   put_inode(*iip);              /* release the old directory */
  1455. 26006   *iip = rip;                   /* acquire the new one */
  1456. 26007   return(OK);
  1457. 26008 }
  1458. 26011 /*===========================================================================*
  1459. 26012  *                              do_stat                                      *
  1460. 26013  *===========================================================================*/
  1461. 26014 PUBLIC int do_stat()
  1462. 26015 {
  1463. 26016 /* Perform the stat(name, buf) system call. */
  1464. 26017
  1465. 26018   register struct inode *rip;
  1466. 26019   register int r;
  1467. 26020
  1468. 26021   /* Both stat() and fstat() use the same routine to do the real work.  That
  1469. 26022    * routine expects an inode, so acquire it temporarily.
  1470. 26023    */
  1471. 26024   if (fetch_name(name1, name1_length, M1) != OK) return(err_code);
  1472. 26025   if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
  1473. 26026   r = stat_inode(rip, NIL_FILP, name2); /* actually do the work.*/
  1474. 26027   put_inode(rip);               /* release the inode */
  1475. 26028   return(r);
  1476. 26029 }
  1477. 26032 /*===========================================================================*
  1478. 26033  *                              do_fstat                                     *
  1479. 26034  *===========================================================================*/
  1480. 26035 PUBLIC int do_fstat()
  1481. 26036 {
  1482. 26037 /* Perform the fstat(fd, buf) system call. */
  1483. 26038
  1484. 26039   register struct filp *rfilp;
  1485. 26040
  1486. 26041   /* Is the file descriptor valid? */
  1487. 26042   if ( (rfilp = get_filp(fd)) == NIL_FILP) return(err_code);
  1488. 26043
  1489. 26044   return(stat_inode(rfilp->filp_ino, rfilp, buffer));
  1490. 26045 }
  1491. 26048 /*===========================================================================*
  1492. 26049  *                              stat_inode                                   *
  1493. 26050  *===========================================================================*/
  1494. 26051 PRIVATE int stat_inode(rip, fil_ptr, user_addr)
  1495. 26052 register struct inode *rip;     /* pointer to inode to stat */
  1496. 26053 struct filp *fil_ptr;           /* filp pointer, supplied by 'fstat' */
  1497. 26054 char *user_addr;                /* user space address where stat buf goes */
  1498. 26055 {
  1499. 26056 /* Common code for stat and fstat system calls. */
  1500. 26057
  1501. 26058   struct stat statbuf;
  1502. 26059   mode_t mo;
  1503. 26060   int r, s;
  1504. 26061
  1505. 26062   /* Update the atime, ctime, and mtime fields in the inode, if need be. */
  1506. 26063   if (rip->i_update) update_times(rip);
  1507. 26064
  1508. .Ep 360 src/fs/stadir.c
  1509. 26065   /* Fill in the statbuf struct. */
  1510. 26066   mo = rip->i_mode & I_TYPE;
  1511. 26067   s = (mo == I_CHAR_SPECIAL || mo == I_BLOCK_SPECIAL);  /* true iff special */
  1512. 26068   statbuf.st_dev = rip->i_dev;
  1513. 26069   statbuf.st_ino = rip->i_num;
  1514. 26070   statbuf.st_mode = rip->i_mode;
  1515. 26071   statbuf.st_nlink = rip->i_nlinks & BYTE;
  1516. 26072   statbuf.st_uid = rip->i_uid;
  1517. 26073   statbuf.st_gid = rip->i_gid & BYTE;
  1518. 26074   statbuf.st_rdev = (dev_t) (s ? rip->i_zone[0] : NO_DEV);
  1519. 26075   statbuf.st_size = rip->i_size;
  1520. 26076
  1521. 26077   if (rip->i_pipe == I_PIPE) {
  1522. 26078         statbuf.st_mode &= ~I_REGULAR;  /* wipe out I_REGULAR bit for pipes */
  1523. 26079         if (fil_ptr != NIL_FILP && fil_ptr->filp_mode & R_BIT) 
  1524. 26080                 statbuf.st_size -= fil_ptr->filp_pos;
  1525. 26081   }
  1526. 26082
  1527. 26083   statbuf.st_atime = rip->i_atime;
  1528. 26084   statbuf.st_mtime = rip->i_mtime;
  1529. 26085   statbuf.st_ctime = rip->i_ctime;
  1530. 26086
  1531. 26087   /* Copy the struct to user space. */
  1532. 26088   r = sys_copy(FS_PROC_NR, D, (phys_bytes) &statbuf,
  1533. 26089                 who, D, (phys_bytes) user_addr, (phys_bytes) sizeof(statbuf));
  1534. 26090   return(r);
  1535. 26091 }
  1536. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1537. src/fs/protect.c    
  1538. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1539. 26100 /* This file deals with protection in the file system.  It contains the code
  1540. 26101  * for four system calls that relate to protection.
  1541. 26102  *
  1542. 26103  * The entry points into this file are
  1543. 26104  *   do_chmod:  perform the CHMOD system call
  1544. 26105  *   do_chown:  perform the CHOWN system call
  1545. 26106  *   do_umask:  perform the UMASK system call
  1546. 26107  *   do_access: perform the ACCESS system call
  1547. 26108  *   forbidden: check to see if a given access is allowed on a given inode
  1548. 26109  */
  1549. 26110
  1550. 26111 #include "fs.h"
  1551. 26112 #include <unistd.h>
  1552. 26113 #include <minix/callnr.h>
  1553. 26114 #include "buf.h"
  1554. 26115 #include "file.h"
  1555. 26116 #include "fproc.h"
  1556. 26117 #include "inode.h"
  1557. 26118 #include "param.h"
  1558. 26119 #include "super.h"
  1559. 26120
  1560. 26121 /*===========================================================================*
  1561. 26122  *                              do_chmod                                     *
  1562. 26123  *===========================================================================*/
  1563. 26124 PUBLIC int do_chmod()
  1564. .Op 361 src/fs/protect.c
  1565. 26125 {
  1566. 26126 /* Perform the chmod(name, mode) system call. */
  1567. 26127
  1568. 26128   register struct inode *rip;
  1569. 26129   register int r;
  1570. 26130
  1571. 26131   /* Temporarily open the file. */
  1572. 26132   if (fetch_name(name, name_length, M3) != OK) return(err_code);
  1573. 26133   if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
  1574. 26134
  1575. 26135   /* Only the owner or the super_user may change the mode of a file.
  1576. 26136    * No one may change the mode of a file on a read-only file system.
  1577. 26137    */
  1578. 26138   if (rip->i_uid != fp->fp_effuid && !super_user)
  1579. 26139         r = EPERM;
  1580. 26140   else
  1581. 26141         r = read_only(rip);
  1582. 26142
  1583. 26143   /* If error, return inode. */
  1584. 26144   if (r != OK)  {
  1585. 26145         put_inode(rip);
  1586. 26146         return(r);
  1587. 26147   }
  1588. 26148
  1589. 26149   /* Now make the change. Clear setgid bit if file is not in caller's grp */
  1590. 26150   rip->i_mode = (rip->i_mode & ~ALL_MODES) | (mode & ALL_MODES);
  1591. 26151   if (!super_user && rip->i_gid != fp->fp_effgid)rip->i_mode &= ~I_SET_GID_BIT;
  1592. 26152   rip->i_update |= CTIME;
  1593. 26153   rip->i_dirt = DIRTY;
  1594. 26154
  1595. 26155   put_inode(rip);
  1596. 26156   return(OK);
  1597. 26157 }
  1598. 26160 /*===========================================================================*
  1599. 26161  *                              do_chown                                     *
  1600. 26162  *===========================================================================*/
  1601. 26163 PUBLIC int do_chown()
  1602. 26164 {
  1603. 26165 /* Perform the chown(name, owner, group) system call. */
  1604. 26166
  1605. 26167   register struct inode *rip;
  1606. 26168   register int r;
  1607. 26169
  1608. 26170   /* Temporarily open the file. */
  1609. 26171   if (fetch_name(name1, name1_length, M1) != OK) return(err_code);
  1610. 26172   if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
  1611. 26173
  1612. 26174   /* Not permitted to change the owner of a file on a read-only file sys. */
  1613. 26175   r = read_only(rip);
  1614. 26176   if (r == OK) {
  1615. 26177         /* FS is R/W.  Whether call is allowed depends on ownership, etc. */
  1616. 26178         if (super_user) {
  1617. 26179                 /* The super user can do anything. */
  1618. 26180                 rip->i_uid = owner;     /* others later */
  1619. 26181         } else {
  1620. 26182                 /* Regular users can only change groups of their own files. */
  1621. 26183                 if (rip->i_uid != fp->fp_effuid) r = EPERM;
  1622. 26184                 if (rip->i_uid != owner) r = EPERM;     /* no giving away */
  1623. .Ep 362 src/fs/protect.c
  1624. 26185                 if (fp->fp_effgid != group) r = EPERM;
  1625. 26186         }
  1626. 26187   }
  1627. 26188   if (r == OK) {
  1628. 26189         rip->i_gid = group;
  1629. 26190         rip->i_mode &= ~(I_SET_UID_BIT | I_SET_GID_BIT);
  1630. 26191         rip->i_update |= CTIME;
  1631. 26192         rip->i_dirt = DIRTY;
  1632. 26193   }
  1633. 26194
  1634. 26195   put_inode(rip);
  1635. 26196   return(r);
  1636. 26197 }
  1637. 26200 /*===========================================================================*
  1638. 26201  *                              do_umask                                     *
  1639. 26202  *===========================================================================*/
  1640. 26203 PUBLIC int do_umask()
  1641. 26204 {
  1642. 26205 /* Perform the umask(co_mode) system call. */
  1643. 26206   register mode_t r;
  1644. 26207
  1645. 26208   r = ~fp->fp_umask;            /* set 'r' to complement of old mask */
  1646. 26209   fp->fp_umask = ~(co_mode & RWX_MODES);
  1647. 26210   return(r);                    /* return complement of old mask */
  1648. 26211 }
  1649. 26214 /*===========================================================================*
  1650. 26215  *                              do_access                                    *
  1651. 26216  *===========================================================================*/
  1652. 26217 PUBLIC int do_access()
  1653. 26218 {
  1654. 26219 /* Perform the access(name, mode) system call. */
  1655. 26220
  1656. 26221   struct inode *rip;
  1657. 26222   register int r;
  1658. 26223
  1659. 26224   /* First check to see if the mode is correct. */
  1660. 26225   if ( (mode & ~(R_OK | W_OK | X_OK)) != 0 && mode != F_OK)
  1661. 26226         return(EINVAL);
  1662. 26227
  1663. 26228   /* Temporarily open the file whose access is to be checked. */
  1664. 26229   if (fetch_name(name, name_length, M3) != OK) return(err_code);
  1665. 26230   if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
  1666. 26231
  1667. 26232   /* Now check the permissions. */
  1668. 26233   r = forbidden(rip, (mode_t) mode);
  1669. 26234   put_inode(rip);
  1670. 26235   return(r);
  1671. 26236 }
  1672. 26239 /*===========================================================================*
  1673. 26240  *                              forbidden                                    *
  1674. 26241  *===========================================================================*/
  1675. 26242 PUBLIC int forbidden(rip, access_desired)
  1676. 26243 register struct inode *rip;     /* pointer to inode to be checked */
  1677. 26244 mode_t access_desired;  /* RWX bits */
  1678. .Op 363 src/fs/protect.c
  1679. 26245 {
  1680. 26246 /* Given a pointer to an inode, 'rip', and the access desired, determine
  1681. 26247  * if the access is allowed, and if not why not.  The routine looks up the
  1682. 26248  * caller's uid in the 'fproc' table.  If access is allowed, OK is returned
  1683. 26249  * if it is forbidden, EACCES is returned.
  1684. 26250  */
  1685. 26251
  1686. 26252   register struct inode *old_rip = rip;
  1687. 26253   register struct super_block *sp;
  1688. 26254   register mode_t bits, perm_bits;
  1689. 26255   int r, shift, test_uid, test_gid;
  1690. 26256
  1691. 26257   if (rip->i_mount == I_MOUNT)  /* The inode is mounted on. */
  1692. 26258         for (sp = &super_block[1]; sp < &super_block[NR_SUPERS]; sp++)
  1693. 26259                 if (sp->s_imount == rip) {
  1694. 26260                         rip = get_inode(sp->s_dev, ROOT_INODE);
  1695. 26261                         break;
  1696. 26262                 } /* if */
  1697. 26263
  1698. 26264   /* Isolate the relevant rwx bits from the mode. */
  1699. 26265   bits = rip->i_mode;
  1700. 26266   test_uid = (fs_call == ACCESS ? fp->fp_realuid : fp->fp_effuid);
  1701. 26267   test_gid = (fs_call == ACCESS ? fp->fp_realgid : fp->fp_effgid);
  1702. 26268   if (test_uid == SU_UID) {
  1703. 26269         /* Grant read and write permission.  Grant search permission for
  1704. 26270          * directories.  Grant execute permission (for non-directories) if
  1705. 26271          * and only if one of the 'X' bits is set.
  1706. 26272          */
  1707. 26273         if ( (bits & I_TYPE) == I_DIRECTORY ||
  1708. 26274              bits & ((X_BIT << 6) | (X_BIT << 3) | X_BIT))
  1709. 26275                 perm_bits = R_BIT | W_BIT | X_BIT;
  1710. 26276         else
  1711. 26277                 perm_bits = R_BIT | W_BIT;
  1712. 26278   } else {
  1713. 26279         if (test_uid == rip->i_uid) shift = 6;          /* owner */
  1714. 26280         else if (test_gid == rip->i_gid ) shift = 3;    /* group */
  1715. 26281         else shift = 0;                                 /* other */
  1716. 26282         perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT);
  1717. 26283   }
  1718. 26284
  1719. 26285   /* If access desired is not a subset of what is allowed, it is refused. */
  1720. 26286   r = OK;
  1721. 26287   if ((perm_bits | access_desired) != perm_bits) r = EACCES;
  1722. 26288
  1723. 26289   /* Check to see if someone is trying to write on a file system that is
  1724. 26290    * mounted read-only.
  1725. 26291    */
  1726. 26292   if (r == OK)
  1727. 26293         if (access_desired & W_BIT) r = read_only(rip);
  1728. 26294
  1729. 26295   if (rip != old_rip) put_inode(rip);
  1730. 26296
  1731. 26297   return(r);
  1732. 26298 }
  1733. 26301 /*===========================================================================*
  1734. 26302  *                              read_only                                    *
  1735. 26303  *===========================================================================*/
  1736. 26304 PUBLIC int read_only(ip)
  1737. .Ep 364 src/fs/protect.c
  1738. 26305 struct inode *ip;               /* ptr to inode whose file sys is to be cked */
  1739. 26306 {
  1740. 26307 /* Check to see if the file system on which the inode 'ip' resides is mounted
  1741. 26308  * read only.  If so, return EROFS, else return OK.
  1742. 26309  */
  1743. 26310
  1744. 26311   register struct super_block *sp;
  1745. 26312
  1746. 26313   sp = ip->i_sp;
  1747. 26314   return(sp->s_rd_only ? EROFS : OK);
  1748. 26315 }
  1749. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1750. src/fs/time.c    
  1751. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1752. 26400 /* This file takes care of those system calls that deal with time.
  1753. 26401  *
  1754. 26402  * The entry points into this file are
  1755. 26403  *   do_utime:  perform the UTIME system call
  1756. 26404  *   do_time:   perform the TIME system call
  1757. 26405  *   do_stime:  perform the STIME system call
  1758. 26406  *   do_tims:   perform the TIMES system call
  1759. 26407  */
  1760. 26408
  1761. 26409 #include "fs.h"
  1762. 26410 #include <minix/callnr.h>
  1763. 26411 #include <minix/com.h>
  1764. 26412 #include "file.h"
  1765. 26413 #include "fproc.h"
  1766. 26414 #include "inode.h"
  1767. 26415 #include "param.h"
  1768. 26416
  1769. 26417 PRIVATE message clock_mess;
  1770. 26418
  1771. 26419 /*===========================================================================*
  1772. 26420  *                              do_utime                                     *
  1773. 26421  *===========================================================================*/
  1774. 26422 PUBLIC int do_utime()
  1775. 26423 {
  1776. 26424 /* Perform the utime(name, timep) system call. */
  1777. 26425
  1778. 26426   register struct inode *rip;
  1779. 26427   register int len, r;
  1780. 26428
  1781. 26429   /* Adjust for case of NULL 'timep'. */
  1782. 26430   len = utime_length;
  1783. 26431   if (len == 0) len = m.m2_i2;
  1784. 26432
  1785. 26433   /* Temporarily open the file. */
  1786. 26434   if (fetch_name(utime_file, len, M1) != OK) return(err_code);
  1787. 26435   if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
  1788. 26436
  1789. 26437   /* Only the owner of a file or the super_user can change its time. */
  1790. 26438   r = OK;
  1791. 26439   if (rip->i_uid != fp->fp_effuid && !super_user) r = EPERM;
  1792. .Op 365 src/fs/time.c
  1793. 26440   if (utime_length == 0 && r != OK) r = forbidden(rip, W_BIT);
  1794. 26441   if (read_only(rip) != OK) r = EROFS;  /* not even su can touch if R/O */
  1795. 26442   if (r == OK) {
  1796. 26443         if (utime_length == 0) {
  1797. 26444                 rip->i_atime = clock_time();
  1798. 26445                 rip->i_mtime = rip->i_atime;
  1799. 26446         } else {
  1800. 26447                 rip->i_atime = utime_actime;
  1801. 26448                 rip->i_mtime = utime_modtime;
  1802. 26449         }
  1803. 26450         rip->i_update = CTIME;  /* discard any stale ATIME and MTIME flags */
  1804. 26451         rip->i_dirt = DIRTY;
  1805. 26452   }
  1806. 26453
  1807. 26454   put_inode(rip);
  1808. 26455   return(r);
  1809. 26456 }
  1810. 26459 /*===========================================================================*
  1811. 26460  *                              do_time                                      *
  1812. 26461  *===========================================================================*/
  1813. 26462 PUBLIC int do_time()
  1814. 26463
  1815. 26464 {
  1816. 26465 /* Perform the time(tp) system call. */
  1817. 26466
  1818. 26467   reply_l1 = clock_time();      /* return time in seconds */
  1819. 26468   return(OK);
  1820. 26469 }
  1821. 26472 /*===========================================================================*
  1822. 26473  *                              do_stime                                     *
  1823. 26474  *===========================================================================*/
  1824. 26475 PUBLIC int do_stime()
  1825. 26476 {
  1826. 26477 /* Perform the stime(tp) system call. */
  1827. 26478
  1828. 26479   register int k;
  1829. 26480
  1830. 26481   if (!super_user) return(EPERM);
  1831. 26482   clock_mess.m_type = SET_TIME;
  1832. 26483   clock_mess.NEW_TIME = (long) tp;
  1833. 26484   if ( (k = sendrec(CLOCK, &clock_mess)) != OK) panic("do_stime error", k);
  1834. 26485   return(OK);
  1835. 26486 }
  1836. 26489 /*===========================================================================*
  1837. 26490  *                              do_tims                                      *
  1838. 26491  *===========================================================================*/
  1839. 26492 PUBLIC int do_tims()
  1840. 26493 {
  1841. 26494 /* Perform the times(buffer) system call. */
  1842. 26495
  1843. 26496   clock_t t[5];
  1844. 26497
  1845. 26498   sys_times(who, t);
  1846. 26499   reply_t1 = t[0];
  1847. .Ep 366 src/fs/time.c
  1848. 26500   reply_t2 = t[1];
  1849. 26501   reply_t3 = t[2];
  1850. 26502   reply_t4 = t[3];
  1851. 26503   reply_t5 = t[4];
  1852. 26504   return(OK);
  1853. 26505 }
  1854. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1855. src/fs/misc.c    
  1856. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1857. 26600 /* This file contains a collection of miscellaneous procedures.  Some of them
  1858. 26601  * perform simple system calls.  Some others do a little part of system calls
  1859. 26602  * that are mostly performed by the Memory Manager.
  1860. 26603  *
  1861. 26604  * The entry points into this file are
  1862. 26605  *   do_dup:      perform the DUP system call
  1863. 26606  *   do_fcntl:    perform the FCNTL system call
  1864. 26607  *   do_sync:     perform the SYNC system call
  1865. 26608  *   do_fork:     adjust the tables after MM has performed a FORK system call
  1866. 26609  *   do_exec:     handle files with FD_CLOEXEC on after MM has done an EXEC
  1867. 26610  *   do_exit:     a process has exited; note that in the tables
  1868. 26611  *   do_set:      set uid or gid for some process
  1869. 26612  *   do_revive:   revive a process that was waiting for something (e.g. TTY)
  1870. 26613  */
  1871. 26614
  1872. 26615 #include "fs.h"
  1873. 26616 #include <fcntl.h>
  1874. 26617 #include <unistd.h>     /* cc runs out of memory with unistd.h :-( */
  1875. 26618 #include <minix/callnr.h>
  1876. 26619 #include <minix/com.h>
  1877. 26620 #include <minix/boot.h>
  1878. 26621 #include "buf.h"
  1879. 26622 #include "file.h"
  1880. 26623 #include "fproc.h"
  1881. 26624 #include "inode.h"
  1882. 26625 #include "dev.h"
  1883. 26626 #include "param.h"
  1884. 26627
  1885. 26628
  1886. 26629 /*===========================================================================*
  1887. 26630  *                              do_dup                                       *
  1888. 26631  *===========================================================================*/
  1889. 26632 PUBLIC int do_dup()
  1890. 26633 {
  1891. 26634 /* Perform the dup(fd) or dup2(fd,fd2) system call. These system calls are
  1892. 26635  * obsolete.  In fact, it is not even possible to invoke them using the
  1893. 26636  * current library because the library routines call fcntl().  They are
  1894. 26637  * provided to permit old binary programs to continue to run.
  1895. 26638  */
  1896. 26639
  1897. 26640   register int rfd;
  1898. 26641   register struct filp *f;
  1899. 26642   struct filp *dummy;
  1900. 26643   int r;
  1901. 26644
  1902. .Op 367 src/fs/misc.c
  1903. 26645   /* Is the file descriptor valid? */
  1904. 26646   rfd = fd & ~DUP_MASK;         /* kill off dup2 bit, if on */
  1905. 26647   if ((f = get_filp(rfd)) == NIL_FILP) return(err_code);
  1906. 26648
  1907. 26649   /* Distinguish between dup and dup2. */
  1908. 26650   if (fd == rfd) {                      /* bit not on */
  1909. 26651         /* dup(fd) */
  1910. 26652         if ( (r = get_fd(0, 0, &fd2, &dummy)) != OK) return(r);
  1911. 26653   } else {
  1912. 26654         /* dup2(fd, fd2) */
  1913. 26655         if (fd2 < 0 || fd2 >= OPEN_MAX) return(EBADF);
  1914. 26656         if (rfd == fd2) return(fd2);    /* ignore the call: dup2(x, x) */
  1915. 26657         fd = fd2;               /* prepare to close fd2 */
  1916. 26658         (void) do_close();      /* cannot fail */
  1917. 26659   }
  1918. 26660
  1919. 26661   /* Success. Set up new file descriptors. */
  1920. 26662   f->filp_count++;
  1921. 26663   fp->fp_filp[fd2] = f;
  1922. 26664   return(fd2);
  1923. 26665 }
  1924. 26667 /*===========================================================================*
  1925. 26668  *                              do_fcntl                                     *
  1926. 26669  *===========================================================================*/
  1927. 26670 PUBLIC int do_fcntl()
  1928. 26671 {
  1929. 26672 /* Perform the fcntl(fd, request, ...) system call. */
  1930. 26673
  1931. 26674   register struct filp *f;
  1932. 26675   int new_fd, r, fl;
  1933. 26676   long cloexec_mask;            /* bit map for the FD_CLOEXEC flag */
  1934. 26677   long clo_value;               /* FD_CLOEXEC flag in proper position */
  1935. 26678   struct filp *dummy;
  1936. 26679
  1937. 26680   /* Is the file descriptor valid? */
  1938. 26681   if ((f = get_filp(fd)) == NIL_FILP) return(err_code);
  1939. 26682
  1940. 26683   switch (request) {
  1941. 26684      case F_DUPFD: 
  1942. 26685         /* This replaces the old dup() system call. */
  1943. 26686         if (addr < 0 || addr >= OPEN_MAX) return(EINVAL);
  1944. 26687         if ((r = get_fd(addr, 0, &new_fd, &dummy)) != OK) return(r);
  1945. 26688         f->filp_count++;
  1946. 26689         fp->fp_filp[new_fd] = f;
  1947. 26690         return(new_fd);
  1948. 26691
  1949. 26692      case F_GETFD: 
  1950. 26693         /* Get close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
  1951. 26694         return( ((fp->fp_cloexec >> fd) & 01) ? FD_CLOEXEC : 0);
  1952. 26695
  1953. 26696      case F_SETFD: 
  1954. 26697         /* Set close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
  1955. 26698         cloexec_mask = 1L << fd;        /* singleton set position ok */
  1956. 26699         clo_value = (addr & FD_CLOEXEC ? cloexec_mask : 0L);
  1957. 26700         fp->fp_cloexec = (fp->fp_cloexec & ~cloexec_mask) | clo_value;
  1958. 26701         return(OK);
  1959. 26702
  1960. 26703      case F_GETFL: 
  1961. 26704         /* Get file status flags (O_NONBLOCK and O_APPEND). */
  1962. .Ep 368 src/fs/misc.c
  1963. 26705         fl = f->filp_flags & (O_NONBLOCK | O_APPEND | O_ACCMODE);
  1964. 26706         return(fl);     
  1965. 26707
  1966. 26708      case F_SETFL: 
  1967. 26709         /* Set file status flags (O_NONBLOCK and O_APPEND). */
  1968. 26710         fl = O_NONBLOCK | O_APPEND;
  1969. 26711         f->filp_flags = (f->filp_flags & ~fl) | (addr & fl);
  1970. 26712         return(OK);
  1971. 26713
  1972. 26714      case F_GETLK:
  1973. 26715      case F_SETLK:
  1974. 26716      case F_SETLKW:
  1975. 26717         /* Set or clear a file lock. */
  1976. 26718         r = lock_op(f, request);
  1977. 26719         return(r);
  1978. 26720
  1979. 26721      default:
  1980. 26722         return(EINVAL);
  1981. 26723   }
  1982. 26724 }
  1983. 26727 /*===========================================================================*
  1984. 26728  *                              do_sync                                      *
  1985. 26729  *===========================================================================*/
  1986. 26730 PUBLIC int do_sync()
  1987. 26731 {
  1988. 26732 /* Perform the sync() system call.  Flush all the tables. */
  1989. 26733
  1990. 26734   register struct inode *rip;
  1991. 26735   register struct buf *bp;
  1992. 26736
  1993. 26737   /* The order in which the various tables are flushed is critical.  The
  1994. 26738    * blocks must be flushed last, since rw_inode() leaves its results in
  1995. 26739    * the block cache.
  1996. 26740    */
  1997. 26741
  1998. 26742   /* Write all the dirty inodes to the disk. */
  1999. 26743   for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++)
  2000. 26744         if (rip->i_count > 0 && rip->i_dirt == DIRTY) rw_inode(rip, WRITING);
  2001. 26745
  2002. 26746   /* Write all the dirty blocks to the disk, one drive at a time. */
  2003. 26747   for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++)
  2004. 26748         if (bp->b_dev != NO_DEV && bp->b_dirt == DIRTY) flushall(bp->b_dev);
  2005. 26749
  2006. 26750   return(OK);           /* sync() can't fail */
  2007. 26751 }
  2008. 26754 /*===========================================================================*
  2009. 26755  *                              do_fork                                      *
  2010. 26756  *===========================================================================*/
  2011. 26757 PUBLIC int do_fork()
  2012. 26758 {
  2013. 26759 /* Perform those aspects of the fork() system call that relate to files.
  2014. 26760  * In particular, let the child inherit its parent's file descriptors.
  2015. 26761  * The parent and child parameters tell who forked off whom. The file
  2016. 26762  * system uses the same slot numbers as the kernel.  Only MM makes this call.
  2017. 26763  */
  2018. 26764
  2019. .Op 369 src/fs/misc.c
  2020. 26765   register struct fproc *cp;
  2021. 26766   int i;
  2022. 26767
  2023. 26768   /* Only MM may make this call directly. */
  2024. 26769   if (who != MM_PROC_NR) return(EGENERIC);
  2025. 26770
  2026. 26771   /* Copy the parent's fproc struct to the child. */
  2027. 26772   fproc[child] = fproc[parent];
  2028. 26773
  2029. 26774   /* Increase the counters in the 'filp' table. */
  2030. 26775   cp = &fproc[child];
  2031. 26776   for (i = 0; i < OPEN_MAX; i++)
  2032. 26777         if (cp->fp_filp[i] != NIL_FILP) cp->fp_filp[i]->filp_count++;
  2033. 26778
  2034. 26779   /* Fill in new process id. */
  2035. 26780   cp->fp_pid = pid;
  2036. 26781
  2037. 26782   /* A child is not a process leader. */
  2038. 26783   cp->fp_sesldr = 0;
  2039. 26784
  2040. 26785   /* Record the fact that both root and working dir have another user. */
  2041. 26786   dup_inode(cp->fp_rootdir);
  2042. 26787   dup_inode(cp->fp_workdir);
  2043. 26788   return(OK);
  2044. 26789 }
  2045. 26792 /*===========================================================================*
  2046. 26793  *                              do_exec                                      *
  2047. 26794  *===========================================================================*/
  2048. 26795 PUBLIC int do_exec()
  2049. 26796 {
  2050. 26797 /* Files can be marked with the FD_CLOEXEC bit (in fp->fp_cloexec).  When
  2051. 26798  * MM does an EXEC, it calls FS to allow FS to find these files and close them.
  2052. 26799  */
  2053. 26800
  2054. 26801   register int i;
  2055. 26802   long bitmap;
  2056. 26803
  2057. 26804   /* Only MM may make this call directly. */
  2058. 26805   if (who != MM_PROC_NR) return(EGENERIC);
  2059. 26806
  2060. 26807   /* The array of FD_CLOEXEC bits is in the fp_cloexec bit map. */
  2061. 26808   fp = &fproc[slot1];           /* get_filp() needs 'fp' */
  2062. 26809   bitmap = fp->fp_cloexec;
  2063. 26810   if (bitmap == 0) return(OK);  /* normal case, no FD_CLOEXECs */
  2064. 26811
  2065. 26812   /* Check the file desriptors one by one for presence of FD_CLOEXEC. */
  2066. 26813   for (i = 0; i < OPEN_MAX; i++) {
  2067. 26814         fd = i;
  2068. 26815         if ( (bitmap >> i) & 01) (void) do_close();
  2069. 26816   }
  2070. 26817
  2071. 26818   return(OK);
  2072. 26819 }
  2073. 26822 /*===========================================================================*
  2074. 26823  *                              do_exit                                      *
  2075. 26824  *===========================================================================*/
  2076. .Ep 370 src/fs/misc.c
  2077. 26825 PUBLIC int do_exit()
  2078. 26826 {
  2079. 26827 /* Perform the file system portion of the exit(status) system call. */
  2080. 26828
  2081. 26829   register int i, exitee, task;
  2082. 26830   register struct fproc *rfp;
  2083. 26831   register struct filp *rfilp;
  2084. 26832   register struct inode *rip;
  2085. 26833   int major;
  2086. 26834   dev_t dev;
  2087. 26835   message dev_mess;
  2088. 26836
  2089. 26837   /* Only MM may do the EXIT call directly. */
  2090. 26838   if (who != MM_PROC_NR) return(EGENERIC);
  2091. 26839
  2092. 26840   /* Nevertheless, pretend that the call came from the user. */
  2093. 26841   fp = &fproc[slot1];           /* get_filp() needs 'fp' */
  2094. 26842   exitee = slot1;
  2095. 26843
  2096. 26844   if (fp->fp_suspended == SUSPENDED) {
  2097. 26845         task = -fp->fp_task;
  2098. 26846         if (task == XPIPE || task == XPOPEN) susp_count--;
  2099. 26847         pro = exitee;
  2100. 26848         (void) do_unpause();    /* this always succeeds for MM */
  2101. 26849         fp->fp_suspended = NOT_SUSPENDED;
  2102. 26850   }
  2103. 26851
  2104. 26852   /* Loop on file descriptors, closing any that are open. */
  2105. 26853   for (i = 0; i < OPEN_MAX; i++) {
  2106. 26854         fd = i;
  2107. 26855         (void) do_close();
  2108. 26856   }
  2109. 26857
  2110. 26858   /* Release root and working directories. */
  2111. 26859   put_inode(fp->fp_rootdir);
  2112. 26860   put_inode(fp->fp_workdir);
  2113. 26861   fp->fp_rootdir = NIL_INODE;
  2114. 26862   fp->fp_workdir = NIL_INODE;
  2115. 26863
  2116. 26864   /* If a session leader exits then revoke access to its controlling tty from
  2117. 26865    * all other processes using it.
  2118. 26866    */
  2119. 26867   if (!fp->fp_sesldr) return(OK);               /* not a session leader */
  2120. 26868   fp->fp_sesldr = FALSE;
  2121. 26869   if (fp->fp_tty == 0) return(OK);              /* no controlling tty */
  2122. 26870   dev = fp->fp_tty;
  2123. 26871
  2124. 26872   for (rfp = &fproc[LOW_USER]; rfp < &fproc[NR_PROCS]; rfp++) {
  2125. 26873         if (rfp->fp_tty == dev) rfp->fp_tty = 0;
  2126. 26874
  2127. 26875         for (i = 0; i < OPEN_MAX; i++) {
  2128. 26876                 if ((rfilp = rfp->fp_filp[i]) == NIL_FILP) continue;
  2129. 26877                 if (rfilp->filp_mode == FILP_CLOSED) continue;
  2130. 26878                 rip = rfilp->filp_ino;
  2131. 26879                 if ((rip->i_mode & I_TYPE) != I_CHAR_SPECIAL) continue;
  2132. 26880                 if ((dev_t) rip->i_zone[0] != dev) continue;
  2133. 26881                 dev_mess.m_type = DEV_CLOSE;
  2134. 26882                 dev_mess.DEVICE = dev;
  2135. 26883                 major = (dev >> MAJOR) & BYTE;  /* major device nr */
  2136. 26884                 task = dmap[major].dmap_task;   /* device task nr */
  2137. .Op 371 src/fs/misc.c
  2138. 26885                 (*dmap[major].dmap_close)(task, &dev_mess);
  2139. 26886                 rfilp->filp_mode = FILP_CLOSED;
  2140. 26887         }
  2141. 26888   }
  2142. 26889   return(OK);
  2143. 26890 }
  2144. 26893 /*===========================================================================*
  2145. 26894  *                              do_set                                       *
  2146. 26895  *===========================================================================*/
  2147. 26896 PUBLIC int do_set()
  2148. 26897 {
  2149. 26898 /* Set uid_t or gid_t field. */
  2150. 26899
  2151. 26900   register struct fproc *tfp;
  2152. 26901
  2153. 26902   /* Only MM may make this call directly. */
  2154. 26903   if (who != MM_PROC_NR) return(EGENERIC);
  2155. 26904
  2156. 26905   tfp = &fproc[slot1];
  2157. 26906   if (fs_call == SETUID) {
  2158. 26907         tfp->fp_realuid = (uid_t) real_user_id;
  2159. 26908         tfp->fp_effuid =  (uid_t) eff_user_id;
  2160. 26909   }
  2161. 26910   if (fs_call == SETGID) {
  2162. 26911         tfp->fp_effgid =  (gid_t) eff_grp_id;
  2163. 26912         tfp->fp_realgid = (gid_t) real_grp_id;
  2164. 26913   }
  2165. 26914   return(OK);
  2166. 26915 }
  2167. 26918 /*===========================================================================*
  2168. 26919  *                              do_revive                                    *
  2169. 26920  *===========================================================================*/
  2170. 26921 PUBLIC int do_revive()
  2171. 26922 {
  2172. 26923 /* A task, typically TTY, has now gotten the characters that were needed for a
  2173. 26924  * previous read.  The process did not get a reply when it made the call.
  2174. 26925  * Instead it was suspended.  Now we can send the reply to wake it up.  This
  2175. 26926  * business has to be done carefully, since the incoming message is from
  2176. 26927  * a task (to which no reply can be sent), and the reply must go to a process
  2177. 26928  * that blocked earlier.  The reply to the caller is inhibited by setting the
  2178. 26929  * 'dont_reply' flag, and the reply to the blocked process is done explicitly
  2179. 26930  * in revive().
  2180. 26931  */
  2181. 26932
  2182. 26933 #if !ALLOW_USER_SEND
  2183. 26934   if (who >= LOW_USER) return(EPERM);
  2184. 26935 #endif
  2185. 26936
  2186. 26937   revive(m.REP_PROC_NR, m.REP_STATUS);
  2187. 26938   dont_reply = TRUE;            /* don't reply to the TTY task */
  2188. 26939   return(OK);
  2189. 26940 }
  2190. .Ep 372 src/fs/device.c
  2191. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2192. src/fs/device.c    
  2193. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2194. 27000 /* When a needed block is not in the cache, it must be fetched from the disk.
  2195. 27001  * Special character files also require I/O.  The routines for these are here.
  2196. 27002  *
  2197. 27003  * The entry points in this file are:
  2198. 27004  *   dev_io:     perform a read or write on a block or character device
  2199. 27005  *   dev_opcl:   perform generic device-specific processing for open & close
  2200. 27006  *   tty_open:   perform tty-specific processing for open
  2201. 27007  *   ctty_open:  perform controlling-tty-specific processing for open
  2202. 27008  *   ctty_close: perform controlling-tty-specific processing for close
  2203. 27009  *   do_setsid:  perform the SETSID system call (FS side)
  2204. 27010  *   do_ioctl:   perform the IOCTL system call
  2205. 27011  *   call_task:  procedure that actually calls the kernel tasks
  2206. 27012  *   call_ctty:  procedure that actually calls task for /dev/tty
  2207. 27013  */
  2208. 27014
  2209. 27015 #include "fs.h"
  2210. 27016 #include <fcntl.h>
  2211. 27017 #include <minix/callnr.h>
  2212. 27018 #include <minix/com.h>
  2213. 27019 #include "dev.h"
  2214. 27020 #include "file.h"
  2215. 27021 #include "fproc.h"
  2216. 27022 #include "inode.h"
  2217. 27023 #include "param.h"
  2218. 27024
  2219. 27025 PRIVATE message dev_mess;
  2220. 27026 PRIVATE major, minor, task;
  2221. 27027
  2222. 27028 FORWARD _PROTOTYPE( void find_dev, (Dev_t dev)                          );
  2223. 27029
  2224. 27030 /*===========================================================================*
  2225. 27031  *                              dev_io                                       *
  2226. 27032  *===========================================================================*/
  2227. 27033 PUBLIC int dev_io(op, nonblock, dev, pos, bytes, proc, buff)
  2228. 27034 int op;                         /* DEV_READ, DEV_WRITE, DEV_IOCTL, etc. */
  2229. 27035 int nonblock;                   /* TRUE if nonblocking op */
  2230. 27036 dev_t dev;                      /* major-minor device number */
  2231. 27037 off_t pos;                      /* byte position */
  2232. 27038 int bytes;                      /* how many bytes to transfer */
  2233. 27039 int proc;                       /* in whose address space is buff? */
  2234. 27040 char *buff;                     /* virtual address of the buffer */
  2235. 27041 {
  2236. 27042 /* Read or write from a device.  The parameter 'dev' tells which one. */
  2237. 27043
  2238. 27044   find_dev(dev);                /* load the variables major, minor, and task */
  2239. 27045
  2240. 27046   /* Set up the message passed to task. */
  2241. 27047   dev_mess.m_type   = op;
  2242. 27048   dev_mess.DEVICE   = (dev >> MINOR) & BYTE;
  2243. 27049   dev_mess.POSITION = pos;
  2244. 27050   dev_mess.PROC_NR  = proc;
  2245. 27051   dev_mess.ADDRESS  = buff;
  2246. 27052   dev_mess.COUNT    = bytes;
  2247. 27053   dev_mess.TTY_FLAGS = nonblock; /* temporary kludge */
  2248. 27054
  2249. .Op 373 src/fs/device.c
  2250. 27055   /* Call the task. */
  2251. 27056   (*dmap[major].dmap_rw)(task, &dev_mess);
  2252. 27057
  2253. 27058   /* Task has completed.  See if call completed. */
  2254. 27059   if (dev_mess.REP_STATUS == SUSPEND) {
  2255. 27060         if (op == DEV_OPEN) task = XPOPEN;
  2256. 27061         suspend(task);          /* suspend user */
  2257. 27062   }
  2258. 27063
  2259. 27064   return(dev_mess.REP_STATUS);
  2260. 27065 }
  2261. 27068 /*===========================================================================*
  2262. 27069  *                              dev_opcl                                     *
  2263. 27070  *===========================================================================*/
  2264. 27071 PUBLIC void dev_opcl(task_nr, mess_ptr)
  2265. 27072 int task_nr;                    /* which task */
  2266. 27073 message *mess_ptr;              /* message pointer */
  2267. 27074 {
  2268. 27075 /* Called from the dmap struct in table.c on opens & closes of special files.*/
  2269. 27076
  2270. 27077   int op;
  2271. 27078
  2272. 27079   op = mess_ptr->m_type;        /* save DEV_OPEN or DEV_CLOSE for later */
  2273. 27080   mess_ptr->DEVICE = (mess_ptr->DEVICE >> MINOR) & BYTE;
  2274. 27081   mess_ptr->PROC_NR = fp - fproc;
  2275. 27082
  2276. 27083   call_task(task_nr, mess_ptr);
  2277. 27084
  2278. 27085   /* Task has completed.  See if call completed. */
  2279. 27086   if (mess_ptr->REP_STATUS == SUSPEND) {
  2280. 27087         if (op == DEV_OPEN) task_nr = XPOPEN;
  2281. 27088         suspend(task_nr);       /* suspend user */
  2282. 27089   }
  2283. 27090 }
  2284. 27092 /*===========================================================================*
  2285. 27093  *                              tty_open                                     *
  2286. 27094  *===========================================================================*/
  2287. 27095 PUBLIC void tty_open(task_nr, mess_ptr)
  2288. 27096 int task_nr;
  2289. 27097 message *mess_ptr;
  2290. 27098 {
  2291. 27099 /* This procedure is called from the dmap struct in table.c on tty opens. */
  2292. 27100   
  2293. 27101   int r;
  2294. 27102   dev_t dev;
  2295. 27103   int flags, proc;
  2296. 27104   register struct fproc *rfp;
  2297. 27105
  2298. 27106   dev = (dev_t) mess_ptr->DEVICE;
  2299. 27107   flags = mess_ptr->COUNT;
  2300. 27108   proc = fp - fproc;
  2301. 27109
  2302. 27110   /* Add O_NOCTTY to the flags if this process is not a session leader, or
  2303. 27111    * if it already has a controlling tty, or if it is someone elses
  2304. 27112    * controlling tty.
  2305. 27113    */
  2306. 27114   if (!fp->fp_sesldr || fp->fp_tty != 0) {
  2307. .Ep 374 src/fs/device.c
  2308. 27115         flags |= O_NOCTTY;
  2309. 27116   } else {
  2310. 27117         for (rfp = &fproc[LOW_USER]; rfp < &fproc[NR_PROCS]; rfp++) {
  2311. 27118                 if (rfp->fp_tty == dev) flags |= O_NOCTTY;
  2312. 27119         }
  2313. 27120   }
  2314. 27121
  2315. 27122   r = dev_io(DEV_OPEN, mode, dev, (off_t) 0, flags, proc, NIL_PTR);
  2316. 27123
  2317. 27124   if (r == 1) {
  2318. 27125         fp->fp_tty = dev;
  2319. 27126         r = OK;
  2320. 27127   }
  2321. 27128
  2322. 27129   mess_ptr->REP_STATUS = r;
  2323. 27130 }
  2324. 27133 /*===========================================================================*
  2325. 27134  *                              ctty_open                                    *
  2326. 27135  *===========================================================================*/
  2327. 27136 PUBLIC void ctty_open(task_nr, mess_ptr)
  2328. 27137 int task_nr;
  2329. 27138 message *mess_ptr;
  2330. 27139 {
  2331. 27140 /* This procedure is called from the dmap struct in table.c on opening
  2332. 27141  * /dev/tty, the magic device that translates to the controlling tty.
  2333. 27142  */
  2334. 27143   
  2335. 27144   mess_ptr->REP_STATUS = fp->fp_tty == 0 ? ENXIO : OK;
  2336. 27145 }
  2337. 27148 /*===========================================================================*
  2338. 27149  *                              ctty_close                                   *
  2339. 27150  *===========================================================================*/
  2340. 27151 PUBLIC void ctty_close(task_nr, mess_ptr)
  2341. 27152 int task_nr;
  2342. 27153 message *mess_ptr;
  2343. 27154 {
  2344. 27155 /* Close /dev/tty. */
  2345. 27156
  2346. 27157   mess_ptr->REP_STATUS = OK;
  2347. 27158 }
  2348. 27161 /*===========================================================================*
  2349. 27162  *                              do_setsid                                    *
  2350. 27163  *===========================================================================*/
  2351. 27164 PUBLIC int do_setsid()
  2352. 27165 {
  2353. 27166 /* Perform the FS side of the SETSID call, i.e. get rid of the controlling
  2354. 27167  * terminal of a process, and make the process a session leader.
  2355. 27168  */
  2356. 27169   register struct fproc *rfp;
  2357. 27170
  2358. 27171   /* Only MM may do the SETSID call directly. */
  2359. 27172   if (who != MM_PROC_NR) return(ENOSYS);
  2360. 27173
  2361. 27174   /* Make the process a session leader with no controlling tty. */
  2362. .Op 375 src/fs/device.c
  2363. 27175   rfp = &fproc[slot1];
  2364. 27176   rfp->fp_sesldr = TRUE;
  2365. 27177   rfp->fp_tty = 0;
  2366. 27178 }
  2367. 27181 /*===========================================================================*
  2368. 27182  *                              do_ioctl                                     *
  2369. 27183  *===========================================================================*/
  2370. 27184 PUBLIC int do_ioctl()
  2371. 27185 {
  2372. 27186 /* Perform the ioctl(ls_fd, request, argx) system call (uses m2 fmt). */
  2373. 27187
  2374. 27188   struct filp *f;
  2375. 27189   register struct inode *rip;
  2376. 27190   dev_t dev;
  2377. 27191
  2378. 27192   if ( (f = get_filp(ls_fd)) == NIL_FILP) return(err_code);
  2379. 27193   rip = f->filp_ino;            /* get inode pointer */
  2380. 27194   if ( (rip->i_mode & I_TYPE) != I_CHAR_SPECIAL
  2381. 27195         && (rip->i_mode & I_TYPE) != I_BLOCK_SPECIAL) return(ENOTTY);
  2382. 27196   dev = (dev_t) rip->i_zone[0];
  2383. 27197   find_dev(dev);
  2384. 27198
  2385. 27199   dev_mess= m;
  2386. 27200
  2387. 27201   dev_mess.m_type  = DEV_IOCTL;
  2388. 27202   dev_mess.PROC_NR = who;
  2389. 27203   dev_mess.TTY_LINE = minor;    
  2390. 27204
  2391. 27205   /* Call the task. */
  2392. 27206   (*dmap[major].dmap_rw)(task, &dev_mess);
  2393. 27207
  2394. 27208   /* Task has completed.  See if call completed. */
  2395. 27209   if (dev_mess.REP_STATUS == SUSPEND) {
  2396. 27210         if (f->filp_flags & O_NONBLOCK) {
  2397. 27211                 /* Not supposed to block. */
  2398. 27212                 dev_mess.m_type = CANCEL;
  2399. 27213                 dev_mess.PROC_NR = who;
  2400. 27214                 dev_mess.TTY_LINE = minor;
  2401. 27215                 (*dmap[major].dmap_rw)(task, &dev_mess);
  2402. 27216                 if (dev_mess.REP_STATUS == EINTR) dev_mess.REP_STATUS = EAGAIN;
  2403. 27217         } else {
  2404. 27218                 suspend(task);          /* User must be suspended. */
  2405. 27219         }
  2406. 27220   }
  2407. 27221   return(dev_mess.REP_STATUS);
  2408. 27222 }
  2409. 27225 /*===========================================================================*
  2410. 27226  *                              find_dev                                     *
  2411. 27227  *===========================================================================*/
  2412. 27228 PRIVATE void find_dev(dev)
  2413. 27229 dev_t dev;                      /* device */
  2414. 27230 {
  2415. 27231 /* Extract the major and minor device number from the parameter. */
  2416. 27232
  2417. 27233   major = (dev >> MAJOR) & BYTE;        /* major device number */
  2418. 27234   minor = (dev >> MINOR) & BYTE;        /* minor device number */
  2419. .Ep 376 src/fs/device.c
  2420. 27235   if (major >= max_major) {
  2421. 27236         major = minor = 0;              /* will fail with ENODEV */
  2422. 27237   }
  2423. 27238   task = dmap[major].dmap_task; /* which task services the device */
  2424. 27239 }
  2425. 27242 /*===========================================================================*
  2426. 27243  *                              call_task                                    *
  2427. 27244  *===========================================================================*/
  2428. 27245 PUBLIC void call_task(task_nr, mess_ptr)
  2429. 27246 int task_nr;                    /* which task to call */
  2430. 27247 message *mess_ptr;              /* pointer to message for task */
  2431. 27248 {
  2432. 27249 /* All file system I/O ultimately comes down to I/O on major/minor device
  2433. 27250  * pairs.  These lead to calls on the following routines via the dmap table.
  2434. 27251  */
  2435. 27252
  2436. 27253   int r, proc_nr;
  2437. 27254   message local_m;
  2438. 27255
  2439. 27256   proc_nr = mess_ptr->PROC_NR;
  2440. 27257
  2441. 27258   while ((r = sendrec(task_nr, mess_ptr)) == ELOCKED) {
  2442. 27259         /* sendrec() failed to avoid deadlock. The task 'task_nr' is
  2443. 27260          * trying to send a REVIVE message for an earlier request.
  2444. 27261          * Handle it and go try again.
  2445. 27262          */
  2446. 27263         if ((r = receive(task_nr, &local_m)) != OK) break;
  2447. 27264
  2448. 27265         /* If we're trying to send a cancel message to a task which has just
  2449. 27266          * sent a completion reply, ignore the reply and abort the cancel
  2450. 27267          * request. The caller will do the revive for the process. 
  2451. 27268          */
  2452. 27269         if (mess_ptr->m_type == CANCEL && local_m.REP_PROC_NR == proc_nr)
  2453. 27270                 return;
  2454. 27271
  2455. 27272         /* Otherwise it should be a REVIVE. */
  2456. 27273         if (local_m.m_type != REVIVE) {
  2457. 27274                 printf(
  2458. 27275                 "fs: strange device reply from %d, type = %d, proc = %dn",
  2459. 27276                         local_m.m_source,
  2460. 27277                         local_m.m_type, local_m.REP_PROC_NR);
  2461. 27278                 continue;
  2462. 27279         }
  2463. 27280
  2464. 27281         revive(local_m.REP_PROC_NR, local_m.REP_STATUS);
  2465. 27282   }
  2466. 27283
  2467. 27284   /* The message received may be a reply to this call, or a REVIVE for some
  2468. 27285    * other process.
  2469. 27286    */
  2470. 27287   for (;;) {
  2471. 27288         if (r != OK) panic("call_task: can't send/receive", NO_NUM);
  2472. 27289
  2473. 27290         /* Did the process we did the sendrec() for get a result? */
  2474. 27291         if (mess_ptr->REP_PROC_NR == proc_nr) break;
  2475. 27292
  2476. 27293         /* Otherwise it should be a REVIVE. */
  2477. 27294         if (mess_ptr->m_type != REVIVE) {
  2478. .Op 377 src/fs/device.c
  2479. 27295                 printf(
  2480. 27296                 "fs: strange device reply from %d, type = %d, proc = %dn",
  2481. 27297                         mess_ptr->m_source,
  2482. 27298                         mess_ptr->m_type, mess_ptr->REP_PROC_NR);
  2483. 27299                 continue;
  2484. 27300         }
  2485. 27301         revive(mess_ptr->REP_PROC_NR, mess_ptr->REP_STATUS);
  2486. 27302
  2487. 27303         r = receive(task_nr, mess_ptr);
  2488. 27304   }
  2489. 27305 }
  2490. 27308 /*===========================================================================*
  2491. 27309  *                              call_ctty                                            *
  2492. 27310  *===========================================================================*/
  2493. 27311 PUBLIC void call_ctty(task_nr, mess_ptr)
  2494. 27312 int task_nr;                    /* not used - for compatibility with dmap_t */
  2495. 27313 message *mess_ptr;              /* pointer to message for task */
  2496. 27314 {
  2497. 27315 /* This routine is only called for one device, namely /dev/tty.  Its job
  2498. 27316  * is to change the message to use the controlling terminal, instead of the
  2499. 27317  * major/minor pair for /dev/tty itself.
  2500. 27318  */
  2501. 27319
  2502. 27320   int major_device;
  2503. 27321  
  2504. 27322   if (fp->fp_tty == 0) {
  2505. 27323         /* No controlling tty present anymore, return an I/O error. */
  2506. 27324         mess_ptr->REP_STATUS = EIO;
  2507. 27325         return;
  2508. 27326   }
  2509. 27327   major_device = (fp->fp_tty >> MAJOR) & BYTE;
  2510. 27328   task_nr = dmap[major_device].dmap_task;       /* task for controlling tty */
  2511. 27329   mess_ptr->DEVICE = (fp->fp_tty >> MINOR) & BYTE;
  2512. 27330   call_task(task_nr, mess_ptr);
  2513. 27331 }
  2514. 27334 /*===========================================================================*
  2515. 27335  *                              no_dev                                       *
  2516. 27336  *===========================================================================*/
  2517. 27337 PUBLIC void no_dev(task_nr, m_ptr)
  2518. 27338 int task_nr;                    /* not used - for compatibility with dmap_t */
  2519. 27339 message *m_ptr;                 /* message pointer */
  2520. 27340 {
  2521. 27341 /* No device there. */
  2522. 27342
  2523. 27343   m_ptr->REP_STATUS = ENODEV;
  2524. 27344 }
  2525. .Ep 378 src/fs/utility.c
  2526. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2527. src/fs/utility.c    
  2528. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2529. 27400 /* This file contains a few general purpose utility routines.
  2530. 27401  *
  2531. 27402  * The entry points into this file are
  2532. 27403  *   clock_time:  ask the clock task for the real time
  2533. 27404  *   copy:        copy a block of data
  2534. 27405  *   fetch_name:  go get a path name from user space
  2535. 27406  *   no_sys:      reject a system call that FS does not handle
  2536. 27407  *   panic:       something awful has occurred;  MINIX cannot continue
  2537. 27408  *   conv2:       do byte swapping on a 16-bit int
  2538. 27409  *   conv4:       do byte swapping on a 32-bit long
  2539. 27410  */
  2540. 27411
  2541. 27412 #include "fs.h"
  2542. 27413 #include <minix/com.h>
  2543. 27414 #include <minix/boot.h>
  2544. 27415 #include <unistd.h>
  2545. 27416 #include "buf.h"
  2546. 27417 #include "file.h"
  2547. 27418 #include "fproc.h"
  2548. 27419 #include "inode.h"
  2549. 27420 #include "param.h"
  2550. 27421
  2551. 27422 PRIVATE int panicking;          /* inhibits recursive panics during sync */
  2552. 27423 PRIVATE message clock_mess;
  2553. 27424
  2554. 27425 /*===========================================================================*
  2555. 27426  *                              clock_time                                   *
  2556. 27427  *===========================================================================*/
  2557. 27428 PUBLIC time_t clock_time()
  2558. 27429 {
  2559. 27430 /* This routine returns the time in seconds since 1.1.1970.  MINIX is an
  2560. 27431  * astrophysically naive system that assumes the earth rotates at a constant
  2561. 27432  * rate and that such things as leap seconds do not exist.
  2562. 27433  */
  2563. 27434
  2564. 27435   register int k;
  2565. 27436
  2566. 27437   clock_mess.m_type = GET_TIME;
  2567. 27438   if ( (k = sendrec(CLOCK, &clock_mess)) != OK) panic("clock_time err", k);
  2568. 27439
  2569. 27440   return( (time_t) clock_mess.NEW_TIME);
  2570. 27441 }
  2571. 27444 /*===========================================================================*
  2572. 27445  *                              fetch_name                                   *
  2573. 27446  *===========================================================================*/
  2574. 27447 PUBLIC int fetch_name(path, len, flag)
  2575. 27448 char *path;                     /* pointer to the path in user space */
  2576. 27449 int len;                        /* path length, including 0 byte */
  2577. 27450 int flag;                       /* M3 means path may be in message */
  2578. 27451 {
  2579. 27452 /* Go get path and put it in 'user_path'.
  2580. 27453  * If 'flag' = M3 and 'len' <= M3_STRING, the path is present in 'message'.
  2581. 27454  * If it is not, go copy it from user space.
  2582. .Op 379 src/fs/utility.c
  2583. 27455  */
  2584. 27456
  2585. 27457   register char *rpu, *rpm;
  2586. 27458   int r;
  2587. 27459
  2588. 27460   /* Check name length for validity. */
  2589. 27461   if (len <= 0) {
  2590. 27462         err_code = EINVAL;
  2591. 27463         return(EGENERIC);
  2592. 27464   }
  2593. 27465
  2594. 27466   if (len > PATH_MAX) {
  2595. 27467         err_code = ENAMETOOLONG;
  2596. 27468         return(EGENERIC);
  2597. 27469   }
  2598. 27470
  2599. 27471   if (flag == M3 && len <= M3_STRING) {
  2600. 27472         /* Just copy the path from the message to 'user_path'. */
  2601. 27473         rpu = &user_path[0];
  2602. 27474         rpm = pathname;         /* contained in input message */
  2603. 27475         do { *rpu++ = *rpm++; } while (--len);
  2604. 27476         r = OK;
  2605. 27477   } else {
  2606. 27478         /* String is not contained in the message.  Get it from user space. */
  2607. 27479         r = sys_copy(who, D, (phys_bytes) path,
  2608. 27480                 FS_PROC_NR, D, (phys_bytes) user_path, (phys_bytes) len);
  2609. 27481   }
  2610. 27482   return(r);
  2611. 27483 }
  2612. 27486 /*===========================================================================*
  2613. 27487  *                              no_sys                                       *
  2614. 27488  *===========================================================================*/
  2615. 27489 PUBLIC int no_sys()
  2616. 27490 {
  2617. 27491 /* Somebody has used an illegal system call number */
  2618. 27492
  2619. 27493   return(EINVAL);
  2620. 27494 }
  2621. 27497 /*===========================================================================*
  2622. 27498  *                              panic                                        *
  2623. 27499  *===========================================================================*/
  2624. 27500 PUBLIC void panic(format, num)
  2625. 27501 char *format;                   /* format string */
  2626. 27502 int num;                        /* number to go with format string */
  2627. 27503 {
  2628. 27504 /* Something awful has happened.  Panics are caused when an internal
  2629. 27505  * inconsistency is detected, e.g., a programming error or illegal value of a
  2630. 27506  * defined constant.
  2631. 27507  */
  2632. 27508
  2633. 27509   if (panicking) return;        /* do not panic during a sync */
  2634. 27510   panicking = TRUE;             /* prevent another panic during the sync */
  2635. 27511   printf("File system panic: %s ", format);
  2636. 27512   if (num != NO_NUM) printf("%d",num); 
  2637. 27513   printf("n");
  2638. 27514   (void) do_sync();             /* flush everything to the disk */
  2639. .Ep 380 src/fs/utility.c
  2640. 27515   sys_abort(RBT_PANIC);
  2641. 27516 }
  2642. 27519 /*===========================================================================*
  2643. 27520  *                              conv2                                        *
  2644. 27521  *===========================================================================*/
  2645. 27522 PUBLIC unsigned conv2(norm, w)
  2646. 27523 int norm;                       /* TRUE if no swap, FALSE for byte swap */
  2647. 27524 int w;                          /* promotion of 16-bit word to be swapped */
  2648. 27525 {
  2649. 27526 /* Possibly swap a 16-bit word between 8086 and 68000 byte order. */
  2650. 27527
  2651. 27528   if (norm) return( (unsigned) w & 0xFFFF);
  2652. 27529   return( ((w&BYTE) << 8) | ( (w>>8) & BYTE));
  2653. 27530 }
  2654. 27533 /*===========================================================================*
  2655. 27534  *                              conv4                                        *
  2656. 27535  *===========================================================================*/
  2657. 27536 PUBLIC long conv4(norm, x)
  2658. 27537 int norm;                       /* TRUE if no swap, FALSE for byte swap */
  2659. 27538 long x;                         /* 32-bit long to be byte swapped */
  2660. 27539 {
  2661. 27540 /* Possibly swap a 32-bit long between 8086 and 68000 byte order. */
  2662. 27541
  2663. 27542   unsigned lo, hi;
  2664. 27543   long l;
  2665. 27544   
  2666. 27545   if (norm) return(x);                  /* byte order was already ok */
  2667. 27546   lo = conv2(FALSE, (int) x & 0xFFFF);  /* low-order half, byte swapped */
  2668. 27547   hi = conv2(FALSE, (int) (x>>16) & 0xFFFF);    /* high-order half, swapped */
  2669. 27548   l = ( (long) lo <<16) | hi;
  2670. 27549   return(l);
  2671. 27550 }
  2672. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2673. src/fs/putk.c    
  2674. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2675. 27600 /* FS must occasionally print some message.  It uses the standard library
  2676. 27601  * routine prink().  (The name "printf" is really a macro defined as "printk").
  2677. 27602  * Printing is done by calling the TTY task directly, not going through FS.
  2678. 27603  */
  2679. 27604
  2680. 27605 #include "fs.h"
  2681. 27606 #include <minix/com.h>
  2682. 27607
  2683. 27608 #define BUF_SIZE          100   /* print buffer size */
  2684. 27609
  2685. 27610 PRIVATE int buf_count;          /* # characters in the buffer */
  2686. 27611 PRIVATE char print_buf[BUF_SIZE];       /* output is buffered here */
  2687. 27612 PRIVATE message putch_msg;      /* used for message to TTY task */
  2688. 27613
  2689. 27614 FORWARD _PROTOTYPE( void flush, (void)                                  );
  2690. .Op 381 src/fs/putk.c
  2691. 27615
  2692. 27616 /*===========================================================================*
  2693. 27617  *                              putk                                         *
  2694. 27618  *===========================================================================*/
  2695. 27619 PUBLIC void putk(c)
  2696. 27620 int c;
  2697. 27621 {
  2698. 27622 /* Accumulate another character.  If 0 or buffer full, print it. */
  2699. 27623
  2700. 27624   if (c == 0 || buf_count == BUF_SIZE) flush();
  2701. 27625   if (c == 'n') putk('r');
  2702. 27626   if (c != 0) print_buf[buf_count++] = c;
  2703. 27627 }
  2704. 27630 /*===========================================================================*
  2705. 27631  *                              flush                                        *
  2706. 27632  *===========================================================================*/
  2707. 27633 PRIVATE void flush()
  2708. 27634 {
  2709. 27635 /* Flush the print buffer by calling TTY task. */
  2710. 27636
  2711. 27637
  2712. 27638   if (buf_count == 0) return;
  2713. 27639   putch_msg.m_type = DEV_WRITE;
  2714. 27640   putch_msg.PROC_NR  = 1;
  2715. 27641   putch_msg.TTY_LINE = 0;
  2716. 27642   putch_msg.ADDRESS  = print_buf;
  2717. 27643   putch_msg.COUNT = buf_count;
  2718. 27644   call_task(TTY, &putch_msg);
  2719. 27645   buf_count = 0;
  2720. 27646 }
  2721. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2722. ./end_of_list    
  2723. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++