A clone of btpd with my configuration changes.

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