file.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. //
  2. // File descriptors
  3. //
  4. #include "types.h"
  5. #include "defs.h"
  6. #include "param.h"
  7. #include "fs.h"
  8. #include "file.h"
  9. #include "spinlock.h"
  10. struct devsw devsw[NDEV];
  11. struct {
  12. struct spinlock lock;
  13. struct file file[NFILE];
  14. } ftable;
  15. void
  16. fileinit(void)
  17. {
  18. memset(&ftable, 0, sizeof(ftable));
  19. initlock(&ftable.lock, "ftable");
  20. }
  21. // Allocate a file structure.
  22. struct file*
  23. filealloc(void)
  24. {
  25. struct file *f;
  26. acquire(&ftable.lock);
  27. for(f = ftable.file; f < ftable.file + NFILE; f++){
  28. if(f->ref == 0){
  29. f->ref = 1;
  30. release(&ftable.lock);
  31. return f;
  32. }
  33. }
  34. release(&ftable.lock);
  35. return 0;
  36. }
  37. // Increment ref count for file f.
  38. struct file*
  39. filedup(struct file *f)
  40. {
  41. acquire(&ftable.lock);
  42. if(f->ref < 1)
  43. panic("filedup");
  44. f->ref++;
  45. release(&ftable.lock);
  46. return f;
  47. }
  48. // Close file f. (Decrement ref count, close when reaches 0.)
  49. void
  50. fileclose(struct file *f)
  51. {
  52. struct file ff;
  53. acquire(&ftable.lock);
  54. if(f->ref < 1)
  55. panic("fileclose");
  56. if(--f->ref > 0){
  57. release(&ftable.lock);
  58. return;
  59. }
  60. ff = *f;
  61. f->ref = 0;
  62. f->type = FD_NONE;
  63. release(&ftable.lock);
  64. if(ff.type == FD_PIPE)
  65. pipeclose(ff.pipe, ff.writable);
  66. else if(ff.type == FD_INODE){
  67. begin_trans();
  68. iput(ff.ip);
  69. commit_trans();
  70. }
  71. }
  72. // Get metadata about file f.
  73. int
  74. filestat(struct file *f, struct stat *st)
  75. {
  76. if(f->type == FD_INODE){
  77. ilock(f->ip);
  78. stati(f->ip, st);
  79. iunlock(f->ip);
  80. return 0;
  81. }
  82. return -1;
  83. }
  84. // Read from file f.
  85. int
  86. fileread(struct file *f, char *addr, int n)
  87. {
  88. int r;
  89. if(f->readable == 0)
  90. return -1;
  91. if(f->type == FD_PIPE)
  92. return piperead(f->pipe, addr, n);
  93. if(f->type == FD_INODE){
  94. ilock(f->ip);
  95. //cprintf("inside fileread\n");
  96. if((r = readi(f->ip, addr, f->off, n)) > 0)
  97. f->off += r;
  98. //cprintf("inside fileread: after readi rv=%x\n", r);
  99. iunlock(f->ip);
  100. return r;
  101. }
  102. panic("fileread");
  103. return -1;
  104. }
  105. //PAGEBREAK!
  106. // Write to file f.
  107. int
  108. filewrite(struct file *f, char *addr, int n)
  109. {
  110. int r;
  111. if(f->writable == 0)
  112. return -1;
  113. //cprintf("inside filewrite\n");
  114. if(f->type == FD_PIPE)
  115. return pipewrite(f->pipe, addr, n);
  116. if(f->type == FD_INODE){
  117. // write a few blocks at a time to avoid exceeding
  118. // the maximum log transaction size, including
  119. // i-node, indirect block, allocation blocks,
  120. // and 2 blocks of slop for non-aligned writes.
  121. // this really belongs lower down, since writei()
  122. // might be writing a device like the console.
  123. int max = ((LOGSIZE-1-1-2) / 2) * 512;
  124. int i = 0;
  125. while(i < n){
  126. int n1 = n - i;
  127. if(n1 > max)
  128. n1 = max;
  129. begin_trans();
  130. ilock(f->ip);
  131. if ((r = writei(f->ip, addr + i, f->off, n1)) > 0)
  132. f->off += r;
  133. iunlock(f->ip);
  134. commit_trans();
  135. if(r < 0)
  136. break;
  137. if(r != n1)
  138. panic("short filewrite");
  139. i += r;
  140. }
  141. return i == n ? n : -1;
  142. }
  143. panic("filewrite");
  144. return -1;
  145. }