chmod.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #define U(x) (x<<6)
  12. #define G(x) (x<<3)
  13. #define O(x) (x)
  14. #define A(x) (U(x)|G(x)|O(x))
  15. #define DMRWE (DMREAD|DMWRITE|DMEXEC)
  16. int parsemode(char *, uint32_t *, uint32_t *);
  17. void
  18. main(int argc, char *argv[])
  19. {
  20. int i;
  21. Dir *dir, ndir;
  22. uint32_t mode, mask;
  23. char *p;
  24. if(argc < 3){
  25. fprint(2, "usage: chmod 0777 file ... or chmod [who]op[rwxalt] file ...\n");
  26. exits("usage");
  27. }
  28. mode = strtol(argv[1], &p, 8);
  29. if(*p == 0)
  30. mask = A(DMRWE);
  31. else if(!parsemode(argv[1], &mask, &mode)){
  32. fprint(2, "chmod: bad mode: %s\n", argv[1]);
  33. exits("mode");
  34. }
  35. nulldir(&ndir);
  36. for(i=2; i<argc; i++){
  37. dir = dirstat(argv[i]);
  38. if(dir == nil){
  39. fprint(2, "chmod: can't stat %s: %r\n", argv[i]);
  40. continue;
  41. }
  42. ndir.mode = (dir->mode & ~mask) | (mode & mask);
  43. free(dir);
  44. if(dirwstat(argv[i], &ndir)==-1){
  45. fprint(2, "chmod: can't wstat %s: %r\n", argv[i]);
  46. continue;
  47. }
  48. }
  49. exits(0);
  50. }
  51. int
  52. parsemode(char *spec, uint32_t *pmask, uint32_t *pmode)
  53. {
  54. uint32_t mode, mask;
  55. int done, op;
  56. char *s;
  57. s = spec;
  58. mask = DMAPPEND | DMEXCL | DMTMP;
  59. for(done=0; !done; ){
  60. switch(*s){
  61. case 'u':
  62. mask |= U(DMRWE); break;
  63. case 'g':
  64. mask |= G(DMRWE); break;
  65. case 'o':
  66. mask |= O(DMRWE); break;
  67. case 'a':
  68. mask |= A(DMRWE); break;
  69. case 0:
  70. return 0;
  71. default:
  72. done = 1;
  73. }
  74. if(!done)
  75. s++;
  76. }
  77. if(s == spec)
  78. mask |= A(DMRWE);
  79. op = *s++;
  80. if(op != '+' && op != '-' && op != '=')
  81. return 0;
  82. mode = 0;
  83. for(; *s ; s++){
  84. switch(*s){
  85. case 'r':
  86. mode |= A(DMREAD); break;
  87. case 'w':
  88. mode |= A(DMWRITE); break;
  89. case 'x':
  90. mode |= A(DMEXEC); break;
  91. case 'a':
  92. mode |= DMAPPEND; break;
  93. case 'l':
  94. mode |= DMEXCL; break;
  95. case 't':
  96. mode |= DMTMP; break;
  97. default:
  98. return 0;
  99. }
  100. }
  101. if(*s != 0)
  102. return 0;
  103. if(op == '+' || op == '-')
  104. mask &= mode;
  105. if(op == '-')
  106. mode = ~mode;
  107. *pmask = mask;
  108. *pmode = mode;
  109. return 1;
  110. }