fcntl.c 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. #include "lib.h"
  2. #include <unistd.h>
  3. #include <errno.h>
  4. #include <stdarg.h>
  5. #include "sys9.h"
  6. /*
  7. * BUG: advisory locking not implemented
  8. */
  9. #define OFL (O_ACCMODE|O_NONBLOCK|O_APPEND)
  10. int
  11. fcntl(int fd, int cmd, ...)
  12. {
  13. int arg, i, ans, err;
  14. Fdinfo *fi, *fans;
  15. va_list va;
  16. unsigned long oflags;
  17. err = 0;
  18. ans = 0;
  19. va_start(va, cmd);
  20. arg = va_arg(va, int);
  21. va_end(va);
  22. fi = &_fdinfo[fd];
  23. if(fd<0 || fd>=OPEN_MAX || !(fi->flags&FD_ISOPEN))
  24. err = EBADF;
  25. else switch(cmd){
  26. case F_DUPFD:
  27. if(fi->flags&(FD_BUFFERED|FD_BUFFEREDX)){
  28. err = EGREG; /* dup of buffered fd not implemented */
  29. break;
  30. }
  31. oflags = fi->oflags;
  32. for(i = (arg>0)? arg : 0; i<OPEN_MAX; i++)
  33. if(!(_fdinfo[i].flags&FD_ISOPEN))
  34. break;
  35. if(i == OPEN_MAX)
  36. err = EMFILE;
  37. else {
  38. ans = _DUP(fd, i);
  39. if(ans != i){
  40. if(ans < 0){
  41. _syserrno();
  42. err = errno;
  43. }else
  44. err = EBADF;
  45. }else{
  46. fans = &_fdinfo[ans];
  47. fans->flags = fi->flags&~FD_CLOEXEC;
  48. fans->oflags = oflags;
  49. fans->uid = fi->uid;
  50. fans->gid = fi->gid;
  51. }
  52. }
  53. break;
  54. case F_GETFD:
  55. ans = fi->flags&FD_CLOEXEC;
  56. break;
  57. case F_SETFD:
  58. fi->flags = (fi->flags&~FD_CLOEXEC)|(arg&FD_CLOEXEC);
  59. break;
  60. case F_GETFL:
  61. ans = fi->oflags&OFL;
  62. break;
  63. case F_SETFL:
  64. fi->oflags = (fi->oflags&~OFL)|(arg&OFL);
  65. break;
  66. case F_GETLK:
  67. case F_SETLK:
  68. case F_SETLKW:
  69. err = EINVAL;
  70. break;
  71. }
  72. if(err){
  73. errno = err;
  74. ans = -1;
  75. }
  76. return ans;
  77. }