wrapper.c 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /*
  2. * Various trivial helper wrappers around standard functions
  3. */
  4. #include "cache.h"
  5. /*
  6. * There's no pack memory to release - but stay close to the Git
  7. * version so wrap this away:
  8. */
  9. static inline void release_pack_memory(size_t size __used, int flag __used)
  10. {
  11. }
  12. char *xstrdup(const char *str)
  13. {
  14. char *ret = strdup(str);
  15. if (!ret) {
  16. release_pack_memory(strlen(str) + 1, -1);
  17. ret = strdup(str);
  18. if (!ret)
  19. die("Out of memory, strdup failed");
  20. }
  21. return ret;
  22. }
  23. void *xmalloc(size_t size)
  24. {
  25. void *ret = malloc(size);
  26. if (!ret && !size)
  27. ret = malloc(1);
  28. if (!ret) {
  29. release_pack_memory(size, -1);
  30. ret = malloc(size);
  31. if (!ret && !size)
  32. ret = malloc(1);
  33. if (!ret)
  34. die("Out of memory, malloc failed");
  35. }
  36. #ifdef XMALLOC_POISON
  37. memset(ret, 0xA5, size);
  38. #endif
  39. return ret;
  40. }
  41. /*
  42. * xmemdupz() allocates (len + 1) bytes of memory, duplicates "len" bytes of
  43. * "data" to the allocated memory, zero terminates the allocated memory,
  44. * and returns a pointer to the allocated memory. If the allocation fails,
  45. * the program dies.
  46. */
  47. void *xmemdupz(const void *data, size_t len)
  48. {
  49. char *p = xmalloc(len + 1);
  50. memcpy(p, data, len);
  51. p[len] = '\0';
  52. return p;
  53. }
  54. char *xstrndup(const char *str, size_t len)
  55. {
  56. char *p = memchr(str, '\0', len);
  57. return xmemdupz(str, p ? (size_t)(p - str) : len);
  58. }
  59. void *xrealloc(void *ptr, size_t size)
  60. {
  61. void *ret = realloc(ptr, size);
  62. if (!ret && !size)
  63. ret = realloc(ptr, 1);
  64. if (!ret) {
  65. release_pack_memory(size, -1);
  66. ret = realloc(ptr, size);
  67. if (!ret && !size)
  68. ret = realloc(ptr, 1);
  69. if (!ret)
  70. die("Out of memory, realloc failed");
  71. }
  72. return ret;
  73. }
  74. void *xcalloc(size_t nmemb, size_t size)
  75. {
  76. void *ret = calloc(nmemb, size);
  77. if (!ret && (!nmemb || !size))
  78. ret = calloc(1, 1);
  79. if (!ret) {
  80. release_pack_memory(nmemb * size, -1);
  81. ret = calloc(nmemb, size);
  82. if (!ret && (!nmemb || !size))
  83. ret = calloc(1, 1);
  84. if (!ret)
  85. die("Out of memory, calloc failed");
  86. }
  87. return ret;
  88. }
  89. void *xmmap(void *start, size_t length,
  90. int prot, int flags, int fd, off_t offset)
  91. {
  92. void *ret = mmap(start, length, prot, flags, fd, offset);
  93. if (ret == MAP_FAILED) {
  94. if (!length)
  95. return NULL;
  96. release_pack_memory(length, fd);
  97. ret = mmap(start, length, prot, flags, fd, offset);
  98. if (ret == MAP_FAILED)
  99. die("Out of memory? mmap failed: %s", strerror(errno));
  100. }
  101. return ret;
  102. }
  103. /*
  104. * xread() is the same a read(), but it automatically restarts read()
  105. * operations with a recoverable error (EAGAIN and EINTR). xread()
  106. * DOES NOT GUARANTEE that "len" bytes is read even if the data is available.
  107. */
  108. ssize_t xread(int fd, void *buf, size_t len)
  109. {
  110. ssize_t nr;
  111. while (1) {
  112. nr = read(fd, buf, len);
  113. if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
  114. continue;
  115. return nr;
  116. }
  117. }
  118. /*
  119. * xwrite() is the same a write(), but it automatically restarts write()
  120. * operations with a recoverable error (EAGAIN and EINTR). xwrite() DOES NOT
  121. * GUARANTEE that "len" bytes is written even if the operation is successful.
  122. */
  123. ssize_t xwrite(int fd, const void *buf, size_t len)
  124. {
  125. ssize_t nr;
  126. while (1) {
  127. nr = write(fd, buf, len);
  128. if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
  129. continue;
  130. return nr;
  131. }
  132. }
  133. ssize_t read_in_full(int fd, void *buf, size_t count)
  134. {
  135. char *p = buf;
  136. ssize_t total = 0;
  137. while (count > 0) {
  138. ssize_t loaded = xread(fd, p, count);
  139. if (loaded <= 0)
  140. return total ? total : loaded;
  141. count -= loaded;
  142. p += loaded;
  143. total += loaded;
  144. }
  145. return total;
  146. }
  147. ssize_t write_in_full(int fd, const void *buf, size_t count)
  148. {
  149. const char *p = buf;
  150. ssize_t total = 0;
  151. while (count > 0) {
  152. ssize_t written = xwrite(fd, p, count);
  153. if (written < 0)
  154. return -1;
  155. if (!written) {
  156. errno = ENOSPC;
  157. return -1;
  158. }
  159. count -= written;
  160. p += written;
  161. total += written;
  162. }
  163. return total;
  164. }
  165. int xdup(int fd)
  166. {
  167. int ret = dup(fd);
  168. if (ret < 0)
  169. die("dup failed: %s", strerror(errno));
  170. return ret;
  171. }
  172. FILE *xfdopen(int fd, const char *mode)
  173. {
  174. FILE *stream = fdopen(fd, mode);
  175. if (stream == NULL)
  176. die("Out of memory? fdopen failed: %s", strerror(errno));
  177. return stream;
  178. }
  179. int xmkstemp(char *template)
  180. {
  181. int fd;
  182. fd = mkstemp(template);
  183. if (fd < 0)
  184. die("Unable to create temporary file: %s", strerror(errno));
  185. return fd;
  186. }