misc_file.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  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, fo, x;
  25. char buf[512] = "";
  26. struct stat st;
  27. #ifndef CYGWIN_HACKS
  28. fi = open(oldpath, O_RDONLY, 0);
  29. #else
  30. fi = open(oldpath, O_RDONLY | O_BINARY, 0);
  31. #endif
  32. if (fi < 0)
  33. return 1;
  34. fstat(fi, &st);
  35. if (!(st.st_mode & S_IFREG))
  36. return 3;
  37. fo = creat(newpath, (int) (st.st_mode & 0600));
  38. if (fo < 0) {
  39. close(fi);
  40. return 2;
  41. }
  42. for (x = 1; x > 0;) {
  43. x = read(fi, buf, 512);
  44. if (x > 0) {
  45. if (write(fo, buf, x) < x) { /* Couldn't write */
  46. close(fo);
  47. close(fi);
  48. unlink(newpath);
  49. return 4;
  50. }
  51. }
  52. }
  53. #ifdef HAVE_FSYNC
  54. fsync(fo);
  55. #endif /* HAVE_FSYNC */
  56. close(fo);
  57. close(fi);
  58. return 0;
  59. }
  60. int movefile(const char *oldpath, const char *newpath)
  61. {
  62. int ret;
  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. 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. file = new char[strlen(tempdir) + 7 + 1];
  135. sprintf(file, "%s.XXXXXX", tempdir);
  136. MakeTemp();
  137. }
  138. Tempfile::Tempfile(const char *prefix)
  139. {
  140. file = new char[strlen(tempdir) + strlen(prefix) + 7 + 1];
  141. sprintf(file, "%s.%s-XXXXXX", tempdir, prefix);
  142. MakeTemp();
  143. }
  144. void Tempfile::MakeTemp()
  145. {
  146. if ((fd = mkstemp(file)) == -1 || (f = fdopen(fd, "wb")) == NULL) {
  147. if (fd != -1) {
  148. unlink(file);
  149. close(fd);
  150. }
  151. fatal("Cannot create temporary file!", 0);
  152. }
  153. }
  154. Tempfile::~Tempfile()
  155. {
  156. close(fd);
  157. unlink(file);
  158. delete[] file;
  159. }