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.

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