rename.c 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. #include "lib.h"
  2. #include <unistd.h>
  3. #include <string.h>
  4. #include <stdio.h>
  5. #include <errno.h>
  6. #include <stdlib.h>
  7. #include "sys9.h"
  8. #include "dir.h"
  9. int
  10. rename(const char *from, const char *to)
  11. {
  12. int n, i;
  13. char *f, *t;
  14. Dir *d, nd;
  15. long mode;
  16. if(access(to, 0) >= 0){
  17. if(_REMOVE(to) < 0){
  18. _syserrno();
  19. return -1;
  20. }
  21. }
  22. if((d = _dirstat(to)) != nil){
  23. free(d);
  24. errno = EEXIST;
  25. return -1;
  26. }
  27. if((d = _dirstat(from)) == nil){
  28. _syserrno();
  29. return -1;
  30. }
  31. f = strrchr(from, '/');
  32. t = strrchr(to, '/');
  33. f = f? f+1 : from;
  34. t = t? t+1 : to;
  35. n = 0;
  36. if(f-from==t-to && strncmp(from, to, f-from)==0){
  37. /* from and to are in same directory (we miss some cases) */
  38. i = strlen(t);
  39. _nulldir(&nd);
  40. nd.name = t;
  41. if(_dirwstat(from, &nd) < 0){
  42. _syserrno();
  43. n = -1;
  44. }
  45. }else{
  46. /* different directories: have to copy */
  47. int ffd, tfd;
  48. char buf[8192];
  49. if((ffd = _OPEN(from, 0)) < 0 ||
  50. (tfd = _CREATE(to, 1, d->mode)) < 0){
  51. _CLOSE(ffd);
  52. _syserrno();
  53. n = -1;
  54. }
  55. while(n>=0 && (n = _READ(ffd, buf, 8192)) > 0)
  56. if(_WRITE(tfd, buf, n) != n){
  57. _syserrno();
  58. n = -1;
  59. }
  60. _CLOSE(ffd);
  61. _CLOSE(tfd);
  62. if(n>0)
  63. n = 0;
  64. if(n == 0) {
  65. if(_REMOVE(from) < 0){
  66. _syserrno();
  67. return -1;
  68. }
  69. }
  70. }
  71. free(d);
  72. return n;
  73. }