fileutils.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. /*
  2. clsync - file tree sync utility based on fanotify and inotify
  3. Copyright (C) 2013 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. #include "common.h"
  16. #include "output.h"
  17. #include "malloc.h"
  18. char *fd2fpath_malloc(int fd) {
  19. struct stat64 lstat;
  20. if(fd <= 0) {
  21. printf_e("Error: Invalid file descriptor supplied: fd2fpath_malloc(%i).\n", fd);
  22. errno = EINVAL;
  23. return NULL;
  24. }
  25. char *fpath = xmalloc((1<<8) + 2);
  26. sprintf(fpath, "/proc/self/fd/%i", fd);
  27. if(lstat64(fpath, &lstat)) {
  28. printf_e("Error: Cannot lstat(\"%s\", lstat): %s (errno: %i).\n", fpath, strerror(errno), errno);
  29. return NULL;
  30. }
  31. ssize_t fpathlen = lstat.st_size;
  32. if(fpathlen > (1<<8))
  33. fpath = xrealloc(fpath, fpathlen+2);
  34. printf_ddd("Debug2: Getting file path from symlink \"%s\". Path length is: %i.\n", fpath, fpathlen);
  35. if((fpathlen = readlink(fpath, fpath, fpathlen+1)) < 0) {
  36. printf_e("Error: Cannot readlink(\"%s\", fpath, bufsize).\n", fpath);
  37. return NULL;
  38. }
  39. printf_ddd("Debug2: The path is: \"%s\"\n", fpath);
  40. fpath[fpathlen] = 0;
  41. return fpath;
  42. }
  43. /**
  44. * @brief Copies file
  45. *
  46. * @param[in] path_from Source file path
  47. * @param[in] path_to Destination file path
  48. *
  49. * @retval zero Successfully copied
  50. * @retval non-zero Got error, while copying
  51. *
  52. */
  53. int fileutils_copy(const char *path_from, const char *path_to) {
  54. char buf[BUFSIZ];
  55. FILE *from, *to;
  56. from = fopen(path_from, "r");
  57. if(from == NULL) {
  58. printf_e("Error: fileutils_copy(\"%s\", \"%s\"): Cannot open file \"%s\" for reading: %s (errno: %i)\n",
  59. path_from, path_to, path_from, strerror(errno), errno);
  60. return errno;
  61. }
  62. to = fopen(path_to, "w");
  63. if(to == NULL) {
  64. printf_e("Error: fileutils_copy(\"%s\", \"%s\"): Cannot open file \"%s\" for writing: %s (errno: %i)\n",
  65. path_from, path_to, path_to, strerror(errno), errno);
  66. return errno;
  67. }
  68. while(!feof(from)) {
  69. int err;
  70. size_t r, w;
  71. r = fread(buf, 1, BUFSIZ, from);
  72. if((err=ferror(from))) {
  73. printf_e("Error: fileutils_copy(\"%s\", \"%s\"): Cannot read from file \"%s\": %s (errno: %i)\n",
  74. path_from, path_to, path_from, strerror(errno), errno);
  75. return errno; // CHECK: Is the "errno" should be used in fread() case?
  76. }
  77. w = fwrite(buf, 1, r, to);
  78. if((err=ferror(to))) {
  79. printf_e("Error: fileutils_copy(\"%s\", \"%s\"): Cannot write to file \"%s\": %s (errno: %i)\n",
  80. path_from, path_to, path_to, strerror(errno), errno);
  81. return errno; // CHECK: is the "errno" should be used in fwrite() case?
  82. }
  83. if(r != w) {
  84. printf_e("Error: fileutils_copy(\"%s\", \"%s\"): Got error while writing to file \"%s\" (%u != %u): %s (errno: %i)\n",
  85. path_from, path_to, path_to, r, w, strerror(errno), errno);
  86. return errno; // CHECK: is the "errno" should be used in case "r != w"?
  87. }
  88. }
  89. return 0;
  90. }
  91. /**
  92. * @brief Calculates directory level of a canonized path (actually it just counts "/"-s)
  93. *
  94. * @param[in] path Canonized path (with realpath())
  95. *
  96. * @retval zero or prositive Direcory level
  97. * @retval negative Got error, while calculation. Error-code is placed to errno.
  98. *
  99. */
  100. short int fileutils_calcdirlevel(const char *path) {
  101. short int dirlevel = 0;
  102. const char *ptr = path;
  103. if(path == NULL) {
  104. printf_e("Error: fileutils_calcdirlevel(): path is NULL.\n");
  105. errno=EINVAL;
  106. return -1;
  107. }
  108. if(*path == 0) {
  109. printf_e("Error: fileutils_calcdirlevel(): path has zero length.\n");
  110. errno=EINVAL;
  111. return -2;
  112. }
  113. if(*path != '/') {
  114. printf_e("Error: fileutils_calcdirlevel(): path \"%s\" is not canonized.\n", path);
  115. errno=EINVAL;
  116. return -3;
  117. }
  118. while(*(ptr++))
  119. if(*ptr == '/')
  120. dirlevel++;
  121. return dirlevel;
  122. }