A clone of btpd with my configuration changes.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

388 lines
7.3 KiB

  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include <errno.h>
  4. #include <fcntl.h>
  5. #include <inttypes.h>
  6. #include <limits.h>
  7. #include <math.h>
  8. #include <pwd.h>
  9. #include <stdarg.h>
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <unistd.h>
  14. void
  15. set_bit(uint8_t *bits, unsigned long index)
  16. {
  17. bits[index / 8] |= (1 << (7 - index % 8));
  18. }
  19. void
  20. clear_bit(uint8_t *bits, unsigned long index)
  21. {
  22. bits[index / 8] &= ~(1 << (7 - index % 8));
  23. }
  24. int
  25. has_bit(const uint8_t *bits, unsigned long index)
  26. {
  27. return bits[index / 8] & (1 << (7 - index % 8));
  28. }
  29. uint8_t
  30. hex2i(char c)
  31. {
  32. if (c >= '0' && c <= '9')
  33. return c - '0';
  34. else if (c >= 'a' && c <= 'f')
  35. return 10 + c - 'a';
  36. else
  37. abort();
  38. }
  39. int
  40. ishex(char *str)
  41. {
  42. while (*str != '\0') {
  43. if (!((*str >= '0' && *str <= '9') || (*str >= 'a' && *str <= 'f')))
  44. return 0;
  45. str++;
  46. }
  47. return 1;
  48. }
  49. uint8_t *
  50. hex2bin(const char *hex, uint8_t *bin, size_t bsize)
  51. {
  52. for (size_t i = 0; i < bsize; i++)
  53. bin[i] = hex2i(hex[i * 2]) << 4 | hex2i(hex[i * 2 + 1]);
  54. return bin;
  55. }
  56. char *
  57. bin2hex(const uint8_t *bin, char *hex, size_t bsize)
  58. {
  59. size_t i;
  60. const char *hexc = "0123456789abcdef";
  61. for (i = 0; i < bsize; i++) {
  62. hex[i * 2] = hexc[(bin[i] >> 4) & 0xf];
  63. hex[i * 2 + 1] = hexc[bin[i] &0xf];
  64. }
  65. hex[i * 2] = '\0';
  66. return hex;
  67. }
  68. int
  69. set_nonblocking(int fd)
  70. {
  71. int oflags;
  72. if ((oflags = fcntl(fd, F_GETFL, 0)) == -1)
  73. return errno;
  74. if (fcntl(fd, F_SETFL, oflags | O_NONBLOCK) == -1)
  75. return errno;
  76. return 0;
  77. }
  78. int
  79. set_blocking(int fd)
  80. {
  81. int oflags;
  82. if ((oflags = fcntl(fd, F_GETFL, 0)) == -1)
  83. return errno;
  84. if (fcntl(fd, F_SETFL, oflags & ~O_NONBLOCK) == -1)
  85. return errno;
  86. return 0;
  87. }
  88. int
  89. mkdirs(char *path, int mode)
  90. {
  91. int err = 0;
  92. char *spos = strchr(path + 1, '/'); // Skip leading '/'
  93. while (spos != NULL) {
  94. *spos = '\0';
  95. err = mkdir(path, mode);
  96. *spos = '/';
  97. if (err != 0 && errno != EEXIST)
  98. return errno;
  99. spos = strchr(spos + 1, '/');
  100. }
  101. if (mkdir(path, mode) != 0)
  102. return errno;
  103. return 0;
  104. }
  105. int
  106. vaopen(int *res, int flags, const char *fmt, va_list ap)
  107. {
  108. int fd, didmkdirs;
  109. char path[PATH_MAX + 1];
  110. if (vsnprintf(path, PATH_MAX, fmt, ap) >= PATH_MAX)
  111. return ENAMETOOLONG;
  112. didmkdirs = 0;
  113. again:
  114. fd = open(path, flags, 0666);
  115. if (fd < 0 && errno == ENOENT && (flags & O_CREAT) != 0 && !didmkdirs) {
  116. char *rs = rindex(path, '/');
  117. if (rs != NULL) {
  118. *rs = '\0';
  119. if (mkdirs(path, 0777) == 0) {
  120. *rs = '/';
  121. didmkdirs = 1;
  122. goto again;
  123. }
  124. }
  125. return errno;
  126. }
  127. if (fd >= 0) {
  128. *res = fd;
  129. return 0;
  130. } else
  131. return errno;
  132. }
  133. int
  134. vopen(int *res, int flags, const char *fmt, ...)
  135. {
  136. int err;
  137. va_list ap;
  138. va_start(ap, fmt);
  139. err = vaopen(res, flags, fmt, ap);
  140. va_end(ap);
  141. return err;
  142. }
  143. int
  144. vfsync(const char *fmt, ...)
  145. {
  146. int err, fd;
  147. va_list ap;
  148. va_start(ap, fmt);
  149. err = vaopen(&fd, O_RDONLY, fmt, ap);
  150. va_end(ap);
  151. if (err != 0)
  152. return err;
  153. if (fsync(fd) < 0)
  154. err = errno;
  155. close(fd);
  156. return err;
  157. }
  158. int
  159. vfopen(FILE **ret, const char *mode, const char *fmt, ...)
  160. {
  161. int err = 0;
  162. char path[PATH_MAX + 1];
  163. va_list ap;
  164. va_start(ap, fmt);
  165. if (vsnprintf(path, PATH_MAX, fmt, ap) >= PATH_MAX)
  166. err = ENAMETOOLONG;
  167. va_end(ap);
  168. if (err == 0)
  169. if ((*ret = fopen(path, mode)) == NULL)
  170. err = errno;
  171. return err;
  172. }
  173. long
  174. rand_between(long min, long max)
  175. {
  176. return min + (long)rint((double)random() * (max - min) / RAND_MAX);
  177. }
  178. int
  179. write_fully(int fd, const void *buf, size_t len)
  180. {
  181. ssize_t nw;
  182. size_t off = 0;
  183. while (off < len) {
  184. nw = write(fd, buf + off, len - off);
  185. if (nw == -1)
  186. return errno;
  187. off += nw;
  188. }
  189. return 0;
  190. }
  191. int
  192. read_fully(int fd, void *buf, size_t len)
  193. {
  194. ssize_t nread;
  195. size_t off = 0;
  196. while (off < len) {
  197. nread = read(fd, buf + off, len - off);
  198. if (nread == 0)
  199. return EIO;
  200. else if (nread == -1)
  201. return errno;
  202. off += nread;
  203. }
  204. return 0;
  205. }
  206. void *
  207. read_file(const char *path, void *buf, size_t *size)
  208. {
  209. int fd, esave;
  210. void *mem = NULL;
  211. struct stat sb;
  212. if ((fd = open(path, O_RDONLY)) == -1)
  213. return NULL;
  214. if (fstat(fd, &sb) == -1)
  215. goto error;
  216. if (*size != 0 && *size < sb.st_size) {
  217. errno = EFBIG;
  218. goto error;
  219. }
  220. *size = sb.st_size;
  221. if (buf == NULL && (mem = malloc(sb.st_size)) == NULL)
  222. goto error;
  223. if (buf == NULL)
  224. buf = mem;
  225. if ((errno = read_fully(fd, buf, *size)) != 0)
  226. goto error;
  227. close(fd);
  228. return buf;
  229. error:
  230. esave = errno;
  231. if (mem != NULL)
  232. free(mem);
  233. close(fd);
  234. errno = esave;
  235. return NULL;
  236. }
  237. char *
  238. find_btpd_dir(void)
  239. {
  240. char *res = getenv("BTPD_HOME");
  241. if (res != NULL)
  242. return strdup(res);
  243. char *home = getenv("HOME");
  244. if (home == NULL) {
  245. struct passwd *pwent = getpwuid(getuid());
  246. endpwent();
  247. if (pwent != NULL)
  248. home = pwent->pw_dir;
  249. }
  250. if (home != NULL)
  251. asprintf(&res, "%s/.btpd", home);
  252. return res;
  253. }
  254. int
  255. make_abs_path(const char *in, char *out)
  256. {
  257. int ii = 0, oi = 0, lastsep = 0;
  258. switch (in[0]) {
  259. case '\0':
  260. return EINVAL;
  261. case '/':
  262. if (strlen(in) >= PATH_MAX)
  263. return ENAMETOOLONG;
  264. out[0] = '/';
  265. oi++;
  266. ii++;
  267. break;
  268. default:
  269. if (getcwd(out, PATH_MAX) == NULL)
  270. return errno;
  271. oi = strlen(out);
  272. if (oi + strlen(in) + 1 >= PATH_MAX)
  273. return ENAMETOOLONG;
  274. out[oi] = '/';
  275. lastsep = oi;
  276. oi++;
  277. break;
  278. }
  279. after_slash:
  280. while (in[ii] == '/')
  281. ii++;
  282. switch(in[ii]) {
  283. case '\0':
  284. goto end;
  285. case '.':
  286. ii++;
  287. goto one_dot;
  288. default:
  289. goto normal;
  290. }
  291. one_dot:
  292. switch (in[ii]) {
  293. case '\0':
  294. goto end;
  295. case '/':
  296. ii++;
  297. goto after_slash;
  298. case '.':
  299. ii++;
  300. goto two_dot;
  301. default:
  302. out[oi] = '.';
  303. oi++;
  304. goto normal;
  305. }
  306. two_dot:
  307. switch (in[ii]) {
  308. case '\0':
  309. if (lastsep == 0)
  310. oi = 1;
  311. else {
  312. oi = lastsep;
  313. while (out[oi - 1] != '/')
  314. oi--;
  315. lastsep = oi - 1;
  316. }
  317. goto end;
  318. case '/':
  319. if (lastsep == 0)
  320. oi = 1;
  321. else {
  322. oi = lastsep;
  323. while (out[oi - 1] != '/')
  324. oi--;
  325. lastsep = oi - 1;
  326. }
  327. ii++;
  328. goto after_slash;
  329. default:
  330. out[oi] = '.';
  331. out[oi + 1] = '.';
  332. oi += 2;
  333. goto normal;
  334. }
  335. normal:
  336. switch (in[ii]) {
  337. case '\0':
  338. goto end;
  339. case '/':
  340. out[oi] = '/';
  341. lastsep = oi;
  342. oi++;
  343. ii++;
  344. goto after_slash;
  345. default:
  346. out[oi] = in[ii];
  347. oi++;
  348. ii++;
  349. goto normal;
  350. }
  351. end:
  352. if (oi == lastsep + 1 && lastsep != 0)
  353. oi = lastsep;
  354. out[oi] = '\0';
  355. return 0;
  356. }