misc_file.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * misc.c -- handles:
  3. * copyfile() movefile()
  4. *
  5. */
  6. #include "common.h"
  7. #include <sys/stat.h>
  8. #include <unistd.h>
  9. #include <fcntl.h>
  10. #include <errno.h>
  11. #include "stat.h"
  12. #include "misc_file.h"
  13. #include "main.h"
  14. /* Copy a file from one place to another (possibly erasing old copy).
  15. *
  16. * returns: 0 if OK
  17. * 1 if can't open original file
  18. * 2 if can't open new file
  19. * 3 if original file isn't normal
  20. * 4 if ran out of disk space
  21. */
  22. int copyfile(const char *oldpath, const char *newpath)
  23. {
  24. int fi;
  25. #ifndef CYGWIN_HACKS
  26. fi = open(oldpath, O_RDONLY, 0);
  27. #else
  28. fi = open(oldpath, O_RDONLY | O_BINARY, 0);
  29. #endif
  30. if (fi < 0)
  31. return 1;
  32. struct stat st;
  33. fstat(fi, &st);
  34. if (!(st.st_mode & S_IFREG))
  35. return 3;
  36. int fo;
  37. fo = creat(newpath, (int) (st.st_mode & 0600));
  38. if (fo < 0) {
  39. close(fi);
  40. return 2;
  41. }
  42. char buf[512] = "";
  43. for (int x = 1; x > 0;) {
  44. x = read(fi, buf, 512);
  45. if (x > 0) {
  46. if (write(fo, buf, x) < x) { /* Couldn't write */
  47. close(fo);
  48. close(fi);
  49. unlink(newpath);
  50. return 4;
  51. }
  52. }
  53. }
  54. #ifdef HAVE_FSYNC
  55. fsync(fo);
  56. #endif /* HAVE_FSYNC */
  57. close(fo);
  58. close(fi);
  59. return 0;
  60. }
  61. int movefile(const char *oldpath, const char *newpath)
  62. {
  63. #ifdef HAVE_RENAME
  64. /* Try to use rename first */
  65. if (!rename(oldpath, newpath))
  66. return 0;
  67. #endif /* HAVE_RENAME */
  68. /* If that fails, fall back to just copying and then
  69. * deleting the file.
  70. */
  71. int ret = copyfile(oldpath, newpath);
  72. if (!ret)
  73. unlink(oldpath);
  74. return ret;
  75. }
  76. int is_file(const char *s)
  77. {
  78. struct stat ss;
  79. int i = stat(s, &ss);
  80. if (i < 0)
  81. return 0;
  82. if ((ss.st_mode & S_IFREG) || (ss.st_mode & S_IFLNK))
  83. return 1;
  84. return 0;
  85. }
  86. int can_stat(const char *s)
  87. {
  88. struct stat ss;
  89. int i = stat(s, &ss);
  90. if (i < 0)
  91. return 0;
  92. return 1;
  93. }
  94. int can_lstat(const char *s)
  95. {
  96. struct stat ss;
  97. int i = lstat(s, &ss);
  98. if (i < 0)
  99. return 0;
  100. return 1;
  101. }
  102. int is_symlink(const char *s)
  103. {
  104. struct stat ss;
  105. int i = lstat(s, &ss);
  106. if (i < 0)
  107. return 0;
  108. if (ss.st_mode & S_IFLNK)
  109. return 1;
  110. return 0;
  111. }
  112. int is_dir(const char *s)
  113. {
  114. struct stat ss;
  115. int i = stat(s, &ss);
  116. if (i < 0)
  117. return 0;
  118. if (ss.st_mode & S_IFDIR)
  119. return 1;
  120. return 0;
  121. }
  122. int fixmod(const char *s)
  123. {
  124. #ifndef CYGWIN_HACKS
  125. if (!can_stat(s))
  126. return 1;
  127. return chmod(s, S_IRUSR | S_IWUSR | S_IXUSR);
  128. #else
  129. return 0;
  130. #endif /* !CYGWIN_HACKS */
  131. }
  132. Tempfile::Tempfile()
  133. {
  134. len = strlen(tempdir) + 1 + 6 + 1;
  135. file = new char[len];
  136. sprintf(file, "%s.XXXXXX", tempdir);
  137. MakeTemp();
  138. }
  139. Tempfile::Tempfile(const char *prefix)
  140. {
  141. len = strlen(tempdir) + 1 + strlen(prefix) + 1 + 6 + 1;
  142. file = new char[len];
  143. sprintf(file, "%s.%s-XXXXXX", tempdir, prefix);
  144. MakeTemp();
  145. }
  146. void Tempfile::MakeTemp()
  147. {
  148. if ((fd = mkstemp(file)) < 0)
  149. goto error;
  150. if ((f = fdopen(fd, "w+b")) == NULL)
  151. goto error;
  152. fchmod(fd, S_IRUSR | S_IWUSR);
  153. return;
  154. error:
  155. putlog(LOG_ERRORS, "Couldn't create temporary file '%s': %s", file, strerror(errno));
  156. delete this;
  157. fatal("Cannot create tempory file!", 0);
  158. }
  159. Tempfile::~Tempfile()
  160. {
  161. unlink(file);
  162. if (f)
  163. fclose(f);
  164. else
  165. close(fd);
  166. delete[] file;
  167. }