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.

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