open.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. #include "fs.h"
  2. #include <sys/stat.h>
  3. #include <string.h>
  4. #include "buf.h"
  5. #include "inode.h"
  6. #include "super.h"
  7. static struct inode *new_node(struct inode *ldirp, char *string, mode_t
  8. bits, uid_t uid, gid_t gid, zone_t z0);
  9. /*===========================================================================*
  10. * fs_create *
  11. *===========================================================================*/
  12. int fs_create(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid,
  13. struct fsdriver_node *node)
  14. {
  15. int r;
  16. struct inode *ldirp;
  17. struct inode *rip;
  18. /* Try to make the file. */
  19. /* Get last directory inode (i.e., directory that will hold the new inode) */
  20. if ((ldirp = get_inode(fs_dev, dir_nr)) == NULL)
  21. return(EINVAL);
  22. /* Create a new inode by calling new_node(). */
  23. rip = new_node(ldirp, name, mode, uid, gid, NO_ZONE);
  24. r = err_code;
  25. /* If an error occurred, release inode. */
  26. if (r != OK) {
  27. put_inode(ldirp);
  28. put_inode(rip);
  29. return(r);
  30. }
  31. /* Reply message */
  32. node->fn_ino_nr = rip->i_num;
  33. node->fn_mode = rip->i_mode;
  34. node->fn_size = rip->i_size;
  35. node->fn_uid = rip->i_uid;
  36. node->fn_gid = rip->i_gid;
  37. node->fn_dev = NO_DEV;
  38. /* Drop parent dir */
  39. put_inode(ldirp);
  40. return(OK);
  41. }
  42. /*===========================================================================*
  43. * fs_mknod *
  44. *===========================================================================*/
  45. int fs_mknod(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid,
  46. dev_t dev)
  47. {
  48. struct inode *ip, *ldirp;
  49. /* Get last directory inode */
  50. if((ldirp = get_inode(fs_dev, dir_nr)) == NULL)
  51. return(EINVAL);
  52. /* Try to create the new node */
  53. ip = new_node(ldirp, name, mode, uid, gid, (zone_t) dev);
  54. put_inode(ip);
  55. put_inode(ldirp);
  56. return(err_code);
  57. }
  58. /*===========================================================================*
  59. * fs_mkdir *
  60. *===========================================================================*/
  61. int fs_mkdir(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid)
  62. {
  63. int r1, r2; /* status codes */
  64. ino_t dot, dotdot; /* inode numbers for . and .. */
  65. struct inode *rip, *ldirp;
  66. /* Get last directory inode */
  67. if((ldirp = get_inode(fs_dev, dir_nr)) == NULL)
  68. return(EINVAL);
  69. /* Next make the inode. If that fails, return error code. */
  70. rip = new_node(ldirp, name, mode, uid, gid, (zone_t) 0);
  71. if(rip == NULL || err_code == EEXIST) {
  72. put_inode(rip); /* can't make dir: it already exists */
  73. put_inode(ldirp);
  74. return(err_code);
  75. }
  76. /* Get the inode numbers for . and .. to enter in the directory. */
  77. dotdot = ldirp->i_num; /* parent's inode number */
  78. dot = rip->i_num; /* inode number of the new dir itself */
  79. /* Now make dir entries for . and .. unless the disk is completely full. */
  80. r1 = search_dir(rip, ".", &dot, ENTER); /* enter . in the new dir */
  81. r2 = search_dir(rip, "..", &dotdot, ENTER); /* enter .. in the new dir */
  82. /* If both . and .. were successfully entered, increment the link counts. */
  83. if (r1 == OK && r2 == OK) {
  84. /* Normal case. It was possible to enter . and .. in the new dir. */
  85. rip->i_nlinks++; /* this accounts for . */
  86. ldirp->i_nlinks++; /* this accounts for .. */
  87. IN_MARKDIRTY(ldirp); /* mark parent's inode as dirty */
  88. } else {
  89. /* It was not possible to enter . or .. probably disk was full -
  90. * links counts haven't been touched. */
  91. if(search_dir(ldirp, name, NULL, DELETE) != OK)
  92. panic("Dir disappeared: %llu", rip->i_num);
  93. rip->i_nlinks--; /* undo the increment done in new_node() */
  94. }
  95. IN_MARKDIRTY(rip); /* either way, i_nlinks has changed */
  96. put_inode(ldirp); /* return the inode of the parent dir */
  97. put_inode(rip); /* return the inode of the newly made dir */
  98. return(err_code); /* new_node() always sets 'err_code' */
  99. }
  100. /*===========================================================================*
  101. * fs_slink *
  102. *===========================================================================*/
  103. int fs_slink(ino_t dir_nr, char *name, uid_t uid, gid_t gid,
  104. struct fsdriver_data *data, size_t bytes)
  105. {
  106. struct inode *sip; /* inode containing symbolic link */
  107. struct inode *ldirp; /* directory containing link */
  108. register int r; /* error code */
  109. struct buf *bp; /* disk buffer for link */
  110. /* Temporarily open the dir. */
  111. if( (ldirp = get_inode(fs_dev, dir_nr)) == NULL)
  112. return(EINVAL);
  113. /* Create the inode for the symlink. */
  114. sip = new_node(ldirp, name, (I_SYMBOLIC_LINK | RWX_MODES), uid, gid, 0);
  115. /* Allocate a disk block for the contents of the symlink.
  116. * Copy contents of symlink (the name pointed to) into first disk block. */
  117. if( (r = err_code) == OK) {
  118. bp = new_block(sip, (off_t) 0);
  119. if (bp == NULL)
  120. r = err_code;
  121. else {
  122. if(get_block_size(sip->i_dev) <= bytes) {
  123. r = ENAMETOOLONG;
  124. } else {
  125. r = fsdriver_copyin(data, 0, b_data(bp), bytes);
  126. b_data(bp)[bytes] = '\0';
  127. }
  128. }
  129. if(bp != NULL && r == OK) {
  130. sip->i_size = (off_t) strlen(b_data(bp));
  131. if(sip->i_size != bytes) {
  132. /* This can happen if the user provides a buffer
  133. * with a \0 in it. This can cause a lot of trouble
  134. * when the symlink is used later. We could just use
  135. * the strlen() value, but we want to let the user
  136. * know he did something wrong. ENAMETOOLONG doesn't
  137. * exactly describe the error, but there is no
  138. * ENAMETOOWRONG.
  139. */
  140. r = ENAMETOOLONG;
  141. }
  142. }
  143. put_block(bp); /* put_block() accepts NULL. */
  144. if(r != OK) {
  145. sip->i_nlinks = NO_LINK;
  146. if(search_dir(ldirp, name, NULL, DELETE) != OK)
  147. panic("Symbolic link vanished");
  148. }
  149. }
  150. /* put_inode() accepts NULL as a noop, so the below are safe. */
  151. put_inode(sip);
  152. put_inode(ldirp);
  153. return(r);
  154. }
  155. /*===========================================================================*
  156. * new_node *
  157. *===========================================================================*/
  158. static struct inode *new_node(struct inode *ldirp,
  159. char *string, mode_t bits, uid_t uid, gid_t gid, zone_t z0)
  160. {
  161. /* New_node() is called by fs_open(), fs_mknod(), and fs_mkdir().
  162. * In all cases it allocates a new inode, makes a directory entry for it in
  163. * the ldirp directory with string name, and initializes it.
  164. * It returns a pointer to the inode if it can do this;
  165. * otherwise it returns NULL. It always sets 'err_code'
  166. * to an appropriate value (OK or an error code).
  167. *
  168. * The parsed path rest is returned in 'parsed' if parsed is nonzero. It
  169. * has to hold at least MFS_NAME_MAX bytes.
  170. */
  171. register struct inode *rip;
  172. register int r;
  173. if (ldirp->i_nlinks == NO_LINK) { /* Dir does not actually exist */
  174. err_code = ENOENT;
  175. return(NULL);
  176. }
  177. if (S_ISDIR(bits) && (ldirp->i_nlinks >= LINK_MAX)) {
  178. /* New entry is a directory, alas we can't give it a ".." */
  179. err_code = EMLINK;
  180. return(NULL);
  181. }
  182. /* Get final component of the path. */
  183. rip = advance(ldirp, string);
  184. if ( rip == NULL && err_code == ENOENT) {
  185. /* Last path component does not exist. Make new directory entry. */
  186. if ( (rip = alloc_inode((ldirp)->i_dev, bits, uid, gid)) == NULL) {
  187. /* Can't creat new inode: out of inodes. */
  188. return(NULL);
  189. }
  190. /* Force inode to the disk before making directory entry to make
  191. * the system more robust in the face of a crash: an inode with
  192. * no directory entry is much better than the opposite.
  193. */
  194. rip->i_nlinks++;
  195. rip->i_zone[0] = z0; /* major/minor device numbers */
  196. rw_inode(rip, WRITING); /* force inode to disk now */
  197. /* New inode acquired. Try to make directory entry. */
  198. if((r=search_dir(ldirp, string, &rip->i_num, ENTER)) != OK) {
  199. rip->i_nlinks--; /* pity, have to free disk inode */
  200. IN_MARKDIRTY(rip); /* dirty inodes are written out */
  201. put_inode(rip); /* this call frees the inode */
  202. err_code = r;
  203. return(NULL);
  204. }
  205. } else {
  206. /* Either last component exists, or there is some problem. */
  207. if (rip != NULL)
  208. r = EEXIST;
  209. else
  210. r = err_code;
  211. }
  212. /* The caller has to return the directory inode (*ldirp). */
  213. err_code = r;
  214. return(rip);
  215. }
  216. /*===========================================================================*
  217. * fs_seek *
  218. *===========================================================================*/
  219. void fs_seek(ino_t ino_nr)
  220. {
  221. struct inode *rip;
  222. /* inhibit read ahead */
  223. if ((rip = find_inode(fs_dev, ino_nr)) != NULL)
  224. rip->i_seek = ISEEK;
  225. }