util.c 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #include <sys/mman.h>
  2. #include <sys/stat.h>
  3. #include <sys/types.h>
  4. #include <fcntl.h>
  5. #include <string.h>
  6. #include <unistd.h>
  7. #include "util.h"
  8. int mkdir_p(char *path, mode_t mode)
  9. {
  10. struct stat st;
  11. int err;
  12. char *d = path;
  13. if (*d != '/')
  14. return -1;
  15. if (stat(path, &st) == 0)
  16. return 0;
  17. while (*++d == '/');
  18. while ((d = strchr(d, '/'))) {
  19. *d = '\0';
  20. err = stat(path, &st) && mkdir(path, mode);
  21. *d++ = '/';
  22. if (err)
  23. return -1;
  24. while (*d == '/')
  25. ++d;
  26. }
  27. return (stat(path, &st) && mkdir(path, mode)) ? -1 : 0;
  28. }
  29. static int slow_copyfile(const char *from, const char *to)
  30. {
  31. int err = 0;
  32. char *line = NULL;
  33. size_t n;
  34. FILE *from_fp = fopen(from, "r"), *to_fp;
  35. if (from_fp == NULL)
  36. goto out;
  37. to_fp = fopen(to, "w");
  38. if (to_fp == NULL)
  39. goto out_fclose_from;
  40. while (getline(&line, &n, from_fp) > 0)
  41. if (fputs(line, to_fp) == EOF)
  42. goto out_fclose_to;
  43. err = 0;
  44. out_fclose_to:
  45. fclose(to_fp);
  46. free(line);
  47. out_fclose_from:
  48. fclose(from_fp);
  49. out:
  50. return err;
  51. }
  52. int copyfile(const char *from, const char *to)
  53. {
  54. int fromfd, tofd;
  55. struct stat st;
  56. void *addr;
  57. int err = -1;
  58. if (stat(from, &st))
  59. goto out;
  60. if (st.st_size == 0) /* /proc? do it slowly... */
  61. return slow_copyfile(from, to);
  62. fromfd = open(from, O_RDONLY);
  63. if (fromfd < 0)
  64. goto out;
  65. tofd = creat(to, 0755);
  66. if (tofd < 0)
  67. goto out_close_from;
  68. addr = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fromfd, 0);
  69. if (addr == MAP_FAILED)
  70. goto out_close_to;
  71. if (write(tofd, addr, st.st_size) == st.st_size)
  72. err = 0;
  73. munmap(addr, st.st_size);
  74. out_close_to:
  75. close(tofd);
  76. if (err)
  77. unlink(to);
  78. out_close_from:
  79. close(fromfd);
  80. out:
  81. return err;
  82. }