PageRenderTime 347ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/lib/bup/_helpers.c

https://gitlab.com/oytunistrator/bup
C | 1406 lines | 1142 code | 208 blank | 56 comment | 236 complexity | f8c1f98c0cb005797449288cf419ed9a MD5 | raw file
  1. #define _LARGEFILE64_SOURCE 1
  2. #define PY_SSIZE_T_CLEAN 1
  3. #undef NDEBUG
  4. #include "../../config/config.h"
  5. // According to Python, its header has to go first:
  6. // http://docs.python.org/2/c-api/intro.html#include-files
  7. #include <Python.h>
  8. #include <assert.h>
  9. #include <errno.h>
  10. #include <fcntl.h>
  11. #include <arpa/inet.h>
  12. #include <stdint.h>
  13. #include <stdlib.h>
  14. #include <stdio.h>
  15. #include <sys/mman.h>
  16. #ifdef HAVE_SYS_TYPES_H
  17. #include <sys/types.h>
  18. #endif
  19. #ifdef HAVE_SYS_STAT_H
  20. #include <sys/stat.h>
  21. #endif
  22. #ifdef HAVE_UNISTD_H
  23. #include <unistd.h>
  24. #endif
  25. #ifdef HAVE_LINUX_FS_H
  26. #include <linux/fs.h>
  27. #endif
  28. #ifdef HAVE_SYS_IOCTL_H
  29. #include <sys/ioctl.h>
  30. #endif
  31. #include "bupsplit.h"
  32. #if defined(FS_IOC_GETFLAGS) && defined(FS_IOC_SETFLAGS)
  33. #define BUP_HAVE_FILE_ATTRS 1
  34. #endif
  35. /*
  36. * Check for incomplete UTIMENSAT support (NetBSD 6), and if so,
  37. * pretend we don't have it.
  38. */
  39. #if !defined(AT_FDCWD) || !defined(AT_SYMLINK_NOFOLLOW)
  40. #undef HAVE_UTIMENSAT
  41. #endif
  42. #ifndef FS_NOCOW_FL
  43. // Of course, this assumes it's a bitfield value.
  44. #define FS_NOCOW_FL 0
  45. #endif
  46. static int istty2 = 0;
  47. #ifndef htonll
  48. // This function should technically be macro'd out if it's going to be used
  49. // more than ocasionally. As of this writing, it'll actually never be called
  50. // in real world bup scenarios (because our packs are < MAX_INT bytes).
  51. static uint64_t htonll(uint64_t value)
  52. {
  53. static const int endian_test = 42;
  54. if (*(char *)&endian_test == endian_test) // LSB-MSB
  55. return ((uint64_t)htonl(value & 0xFFFFFFFF) << 32) | htonl(value >> 32);
  56. return value; // already in network byte order MSB-LSB
  57. }
  58. #endif
  59. #define INTEGRAL_ASSIGNMENT_FITS(dest, src) \
  60. ({ \
  61. *(dest) = (src); \
  62. *(dest) == (src) && (*(dest) < 1) == ((src) < 1); \
  63. })
  64. // At the moment any code that calls INTGER_TO_PY() will have to
  65. // disable -Wtautological-compare for clang. See below.
  66. #define INTEGER_TO_PY(x) \
  67. (((x) >= 0) ? PyLong_FromUnsignedLongLong(x) : PyLong_FromLongLong(x))
  68. static int bup_ulong_from_pyint(unsigned long *x, PyObject *py,
  69. const char *name)
  70. {
  71. const long tmp = PyInt_AsLong(py);
  72. if (tmp == -1 && PyErr_Occurred())
  73. {
  74. if (PyErr_ExceptionMatches(PyExc_OverflowError))
  75. PyErr_Format(PyExc_OverflowError, "%s too big for unsigned long",
  76. name);
  77. return 0;
  78. }
  79. if (tmp < 0)
  80. {
  81. PyErr_Format(PyExc_OverflowError,
  82. "negative %s cannot be converted to unsigned long", name);
  83. return 0;
  84. }
  85. *x = tmp;
  86. return 1;
  87. }
  88. static int bup_ulong_from_py(unsigned long *x, PyObject *py, const char *name)
  89. {
  90. if (PyInt_Check(py))
  91. return bup_ulong_from_pyint(x, py, name);
  92. if (!PyLong_Check(py))
  93. {
  94. PyErr_Format(PyExc_TypeError, "expected integer %s", name);
  95. return 0;
  96. }
  97. const unsigned long tmp = PyLong_AsUnsignedLong(py);
  98. if (PyErr_Occurred())
  99. {
  100. if (PyErr_ExceptionMatches(PyExc_OverflowError))
  101. PyErr_Format(PyExc_OverflowError, "%s too big for unsigned long",
  102. name);
  103. return 0;
  104. }
  105. *x = tmp;
  106. return 1;
  107. }
  108. static int bup_uint_from_py(unsigned int *x, PyObject *py, const char *name)
  109. {
  110. unsigned long tmp;
  111. if (!bup_ulong_from_py(&tmp, py, name))
  112. return 0;
  113. if (tmp > UINT_MAX)
  114. {
  115. PyErr_Format(PyExc_OverflowError, "%s too big for unsigned int", name);
  116. return 0;
  117. }
  118. *x = tmp;
  119. return 1;
  120. }
  121. static int bup_ullong_from_py(unsigned PY_LONG_LONG *x, PyObject *py,
  122. const char *name)
  123. {
  124. if (PyInt_Check(py))
  125. {
  126. unsigned long tmp;
  127. if (bup_ulong_from_pyint(&tmp, py, name))
  128. {
  129. *x = tmp;
  130. return 1;
  131. }
  132. return 0;
  133. }
  134. if (!PyLong_Check(py))
  135. {
  136. PyErr_Format(PyExc_TypeError, "integer argument expected for %s", name);
  137. return 0;
  138. }
  139. const unsigned PY_LONG_LONG tmp = PyLong_AsUnsignedLongLong(py);
  140. if (tmp == (unsigned long long) -1 && PyErr_Occurred())
  141. {
  142. if (PyErr_ExceptionMatches(PyExc_OverflowError))
  143. PyErr_Format(PyExc_OverflowError,
  144. "%s too big for unsigned long long", name);
  145. return 0;
  146. }
  147. *x = tmp;
  148. return 1;
  149. }
  150. // Probably we should use autoconf or something and set HAVE_PY_GETARGCARGV...
  151. #if __WIN32__ || __CYGWIN__
  152. // There's no 'ps' on win32 anyway, and Py_GetArgcArgv() isn't available.
  153. static void unpythonize_argv(void) { }
  154. #else // not __WIN32__
  155. // For some reason this isn't declared in Python.h
  156. extern void Py_GetArgcArgv(int *argc, char ***argv);
  157. static void unpythonize_argv(void)
  158. {
  159. int argc, i;
  160. char **argv, *arge;
  161. Py_GetArgcArgv(&argc, &argv);
  162. for (i = 0; i < argc-1; i++)
  163. {
  164. if (argv[i] + strlen(argv[i]) + 1 != argv[i+1])
  165. {
  166. // The argv block doesn't work the way we expected; it's unsafe
  167. // to mess with it.
  168. return;
  169. }
  170. }
  171. arge = argv[argc-1] + strlen(argv[argc-1]) + 1;
  172. if (strstr(argv[0], "python") && argv[1] == argv[0] + strlen(argv[0]) + 1)
  173. {
  174. char *p;
  175. size_t len, diff;
  176. p = strrchr(argv[1], '/');
  177. if (p)
  178. {
  179. p++;
  180. diff = p - argv[0];
  181. len = arge - p;
  182. memmove(argv[0], p, len);
  183. memset(arge - diff, 0, diff);
  184. for (i = 0; i < argc; i++)
  185. argv[i] = argv[i+1] ? argv[i+1]-diff : NULL;
  186. }
  187. }
  188. }
  189. #endif // not __WIN32__ or __CYGWIN__
  190. static unsigned long long count_leading_zeros(const unsigned char * const buf,
  191. unsigned long long len)
  192. {
  193. const unsigned char *cur = buf;
  194. while(len-- && *cur == 0)
  195. cur++;
  196. return cur - buf;
  197. }
  198. static int write_all(int fd, const void *buf, const size_t count)
  199. {
  200. size_t written = 0;
  201. while (written < count)
  202. {
  203. const ssize_t rc = write(fd, buf + written, count - written);
  204. if (rc == -1)
  205. return -1;
  206. written += rc;
  207. }
  208. return 0;
  209. }
  210. static int uadd(unsigned long long *dest,
  211. const unsigned long long x,
  212. const unsigned long long y)
  213. {
  214. const unsigned long long result = x + y;
  215. if (result < x || result < y)
  216. return 0;
  217. *dest = result;
  218. return 1;
  219. }
  220. static PyObject *bup_write_sparsely(PyObject *self, PyObject *args)
  221. {
  222. int fd;
  223. unsigned char *buf = NULL;
  224. Py_ssize_t sbuf_len;
  225. PyObject *py_min_sparse_len, *py_prev_sparse_len;
  226. if (!PyArg_ParseTuple(args, "it#OO",
  227. &fd, &buf, &sbuf_len,
  228. &py_min_sparse_len, &py_prev_sparse_len))
  229. return NULL;
  230. unsigned long long min_sparse_len, prev_sparse_len, buf_len;
  231. if (!bup_ullong_from_py(&min_sparse_len, py_min_sparse_len, "min_sparse_len"))
  232. return NULL;
  233. if (!bup_ullong_from_py(&prev_sparse_len, py_prev_sparse_len, "prev_sparse_len"))
  234. return NULL;
  235. if (sbuf_len < 0)
  236. return PyErr_Format(PyExc_ValueError, "negative bufer length");
  237. if (!INTEGRAL_ASSIGNMENT_FITS(&buf_len, sbuf_len))
  238. return PyErr_Format(PyExc_OverflowError, "buffer length too large");
  239. // For now, there are some cases where we just give up if the
  240. // values are too large, but we could try to break up the relevant
  241. // operations into chunks.
  242. // Deal with preceding zeros. Just make them sparse, along with
  243. // any leading zeros in buf, even if the region's not >= min,
  244. // since the alternative is a potentially extra small write.
  245. if (prev_sparse_len)
  246. {
  247. const unsigned long long zeros = count_leading_zeros(buf, buf_len);
  248. unsigned long long new_sparse_len = 0;
  249. if (!uadd(&new_sparse_len, prev_sparse_len, zeros))
  250. return PyErr_Format (PyExc_OverflowError, "sparse region too large");
  251. if (zeros == buf_len)
  252. return PyLong_FromUnsignedLongLong(new_sparse_len);
  253. off_t new_off;
  254. if (!INTEGRAL_ASSIGNMENT_FITS(&new_off, new_sparse_len))
  255. return PyErr_Format(PyExc_OverflowError,
  256. "sparse region too large for seek");
  257. const off_t off = lseek(fd, new_off, SEEK_CUR);
  258. if (off == -1)
  259. return PyErr_SetFromErrno(PyExc_IOError);
  260. buf += zeros;
  261. buf_len -= zeros;
  262. }
  263. int rc;
  264. unsigned long long unexamined = buf_len;
  265. unsigned char *block_start = buf, *cur = buf;
  266. while(unexamined)
  267. {
  268. const unsigned long long zeros = count_leading_zeros(cur, unexamined);
  269. assert(zeros <= unexamined);
  270. unexamined -= zeros;
  271. if (unexamined == 0) // Runs off the end.
  272. {
  273. rc = write_all(fd, block_start, cur - block_start);
  274. if (rc)
  275. return PyErr_SetFromErrno(PyExc_IOError);
  276. return PyLong_FromUnsignedLongLong(zeros);
  277. }
  278. cur += zeros;
  279. if (zeros >= min_sparse_len)
  280. {
  281. off_t new_off;
  282. if (!INTEGRAL_ASSIGNMENT_FITS(&new_off, zeros))
  283. return PyErr_Format(PyExc_ValueError,
  284. "zero count overflows off_t");
  285. off_t off = lseek(fd, new_off, SEEK_CUR);
  286. if (off == -1)
  287. return PyErr_SetFromErrno(PyExc_IOError);
  288. block_start = cur;
  289. }
  290. while (unexamined && *cur != 0)
  291. {
  292. cur++; unexamined--;
  293. }
  294. }
  295. rc = write_all(fd, block_start, cur - block_start);
  296. if (rc)
  297. return PyErr_SetFromErrno(PyExc_IOError);
  298. return PyInt_FromLong(0);
  299. }
  300. static PyObject *selftest(PyObject *self, PyObject *args)
  301. {
  302. if (!PyArg_ParseTuple(args, ""))
  303. return NULL;
  304. return Py_BuildValue("i", !bupsplit_selftest());
  305. }
  306. static PyObject *blobbits(PyObject *self, PyObject *args)
  307. {
  308. if (!PyArg_ParseTuple(args, ""))
  309. return NULL;
  310. return Py_BuildValue("i", BUP_BLOBBITS);
  311. }
  312. static PyObject *splitbuf(PyObject *self, PyObject *args)
  313. {
  314. unsigned char *buf = NULL;
  315. Py_ssize_t len = 0;
  316. int out = 0, bits = -1;
  317. if (!PyArg_ParseTuple(args, "t#", &buf, &len))
  318. return NULL;
  319. assert(len <= INT_MAX);
  320. out = bupsplit_find_ofs(buf, len, &bits);
  321. if (out) assert(bits >= BUP_BLOBBITS);
  322. return Py_BuildValue("ii", out, bits);
  323. }
  324. static PyObject *bitmatch(PyObject *self, PyObject *args)
  325. {
  326. unsigned char *buf1 = NULL, *buf2 = NULL;
  327. Py_ssize_t len1 = 0, len2 = 0;
  328. Py_ssize_t byte;
  329. int bit;
  330. if (!PyArg_ParseTuple(args, "t#t#", &buf1, &len1, &buf2, &len2))
  331. return NULL;
  332. bit = 0;
  333. for (byte = 0; byte < len1 && byte < len2; byte++)
  334. {
  335. int b1 = buf1[byte], b2 = buf2[byte];
  336. if (b1 != b2)
  337. {
  338. for (bit = 0; bit < 8; bit++)
  339. if ( (b1 & (0x80 >> bit)) != (b2 & (0x80 >> bit)) )
  340. break;
  341. break;
  342. }
  343. }
  344. assert(byte <= (INT_MAX >> 3));
  345. return Py_BuildValue("i", byte*8 + bit);
  346. }
  347. static PyObject *firstword(PyObject *self, PyObject *args)
  348. {
  349. unsigned char *buf = NULL;
  350. Py_ssize_t len = 0;
  351. uint32_t v;
  352. if (!PyArg_ParseTuple(args, "t#", &buf, &len))
  353. return NULL;
  354. if (len < 4)
  355. return NULL;
  356. v = ntohl(*(uint32_t *)buf);
  357. return PyLong_FromUnsignedLong(v);
  358. }
  359. #define BLOOM2_HEADERLEN 16
  360. static void to_bloom_address_bitmask4(const unsigned char *buf,
  361. const int nbits, uint64_t *v, unsigned char *bitmask)
  362. {
  363. int bit;
  364. uint32_t high;
  365. uint64_t raw, mask;
  366. memcpy(&high, buf, 4);
  367. mask = (1<<nbits) - 1;
  368. raw = (((uint64_t)ntohl(high) << 8) | buf[4]);
  369. bit = (raw >> (37-nbits)) & 0x7;
  370. *v = (raw >> (40-nbits)) & mask;
  371. *bitmask = 1 << bit;
  372. }
  373. static void to_bloom_address_bitmask5(const unsigned char *buf,
  374. const int nbits, uint32_t *v, unsigned char *bitmask)
  375. {
  376. int bit;
  377. uint32_t high;
  378. uint32_t raw, mask;
  379. memcpy(&high, buf, 4);
  380. mask = (1<<nbits) - 1;
  381. raw = ntohl(high);
  382. bit = (raw >> (29-nbits)) & 0x7;
  383. *v = (raw >> (32-nbits)) & mask;
  384. *bitmask = 1 << bit;
  385. }
  386. #define BLOOM_SET_BIT(name, address, otype) \
  387. static void name(unsigned char *bloom, const unsigned char *buf, const int nbits)\
  388. {\
  389. unsigned char bitmask;\
  390. otype v;\
  391. address(buf, nbits, &v, &bitmask);\
  392. bloom[BLOOM2_HEADERLEN+v] |= bitmask;\
  393. }
  394. BLOOM_SET_BIT(bloom_set_bit4, to_bloom_address_bitmask4, uint64_t)
  395. BLOOM_SET_BIT(bloom_set_bit5, to_bloom_address_bitmask5, uint32_t)
  396. #define BLOOM_GET_BIT(name, address, otype) \
  397. static int name(const unsigned char *bloom, const unsigned char *buf, const int nbits)\
  398. {\
  399. unsigned char bitmask;\
  400. otype v;\
  401. address(buf, nbits, &v, &bitmask);\
  402. return bloom[BLOOM2_HEADERLEN+v] & bitmask;\
  403. }
  404. BLOOM_GET_BIT(bloom_get_bit4, to_bloom_address_bitmask4, uint64_t)
  405. BLOOM_GET_BIT(bloom_get_bit5, to_bloom_address_bitmask5, uint32_t)
  406. static PyObject *bloom_add(PyObject *self, PyObject *args)
  407. {
  408. unsigned char *sha = NULL, *bloom = NULL;
  409. unsigned char *end;
  410. Py_ssize_t len = 0, blen = 0;
  411. int nbits = 0, k = 0;
  412. if (!PyArg_ParseTuple(args, "w#s#ii", &bloom, &blen, &sha, &len, &nbits, &k))
  413. return NULL;
  414. if (blen < 16+(1<<nbits) || len % 20 != 0)
  415. return NULL;
  416. if (k == 5)
  417. {
  418. if (nbits > 29)
  419. return NULL;
  420. for (end = sha + len; sha < end; sha += 20/k)
  421. bloom_set_bit5(bloom, sha, nbits);
  422. }
  423. else if (k == 4)
  424. {
  425. if (nbits > 37)
  426. return NULL;
  427. for (end = sha + len; sha < end; sha += 20/k)
  428. bloom_set_bit4(bloom, sha, nbits);
  429. }
  430. else
  431. return NULL;
  432. return Py_BuildValue("n", len/20);
  433. }
  434. static PyObject *bloom_contains(PyObject *self, PyObject *args)
  435. {
  436. unsigned char *sha = NULL, *bloom = NULL;
  437. Py_ssize_t len = 0, blen = 0;
  438. int nbits = 0, k = 0;
  439. unsigned char *end;
  440. int steps;
  441. if (!PyArg_ParseTuple(args, "t#s#ii", &bloom, &blen, &sha, &len, &nbits, &k))
  442. return NULL;
  443. if (len != 20)
  444. return NULL;
  445. if (k == 5)
  446. {
  447. if (nbits > 29)
  448. return NULL;
  449. for (steps = 1, end = sha + 20; sha < end; sha += 20/k, steps++)
  450. if (!bloom_get_bit5(bloom, sha, nbits))
  451. return Py_BuildValue("Oi", Py_None, steps);
  452. }
  453. else if (k == 4)
  454. {
  455. if (nbits > 37)
  456. return NULL;
  457. for (steps = 1, end = sha + 20; sha < end; sha += 20/k, steps++)
  458. if (!bloom_get_bit4(bloom, sha, nbits))
  459. return Py_BuildValue("Oi", Py_None, steps);
  460. }
  461. else
  462. return NULL;
  463. return Py_BuildValue("ii", 1, k);
  464. }
  465. static uint32_t _extract_bits(unsigned char *buf, int nbits)
  466. {
  467. uint32_t v, mask;
  468. mask = (1<<nbits) - 1;
  469. v = ntohl(*(uint32_t *)buf);
  470. v = (v >> (32-nbits)) & mask;
  471. return v;
  472. }
  473. static PyObject *extract_bits(PyObject *self, PyObject *args)
  474. {
  475. unsigned char *buf = NULL;
  476. Py_ssize_t len = 0;
  477. int nbits = 0;
  478. if (!PyArg_ParseTuple(args, "t#i", &buf, &len, &nbits))
  479. return NULL;
  480. if (len < 4)
  481. return NULL;
  482. return PyLong_FromUnsignedLong(_extract_bits(buf, nbits));
  483. }
  484. struct sha {
  485. unsigned char bytes[20];
  486. };
  487. struct idx {
  488. unsigned char *map;
  489. struct sha *cur;
  490. struct sha *end;
  491. uint32_t *cur_name;
  492. Py_ssize_t bytes;
  493. int name_base;
  494. };
  495. static int _cmp_sha(const struct sha *sha1, const struct sha *sha2)
  496. {
  497. int i;
  498. for (i = 0; i < sizeof(struct sha); i++)
  499. if (sha1->bytes[i] != sha2->bytes[i])
  500. return sha1->bytes[i] - sha2->bytes[i];
  501. return 0;
  502. }
  503. static void _fix_idx_order(struct idx **idxs, int *last_i)
  504. {
  505. struct idx *idx;
  506. int low, mid, high, c = 0;
  507. idx = idxs[*last_i];
  508. if (idxs[*last_i]->cur >= idxs[*last_i]->end)
  509. {
  510. idxs[*last_i] = NULL;
  511. PyMem_Free(idx);
  512. --*last_i;
  513. return;
  514. }
  515. if (*last_i == 0)
  516. return;
  517. low = *last_i-1;
  518. mid = *last_i;
  519. high = 0;
  520. while (low >= high)
  521. {
  522. mid = (low + high) / 2;
  523. c = _cmp_sha(idx->cur, idxs[mid]->cur);
  524. if (c < 0)
  525. high = mid + 1;
  526. else if (c > 0)
  527. low = mid - 1;
  528. else
  529. break;
  530. }
  531. if (c < 0)
  532. ++mid;
  533. if (mid == *last_i)
  534. return;
  535. memmove(&idxs[mid+1], &idxs[mid], (*last_i-mid)*sizeof(struct idx *));
  536. idxs[mid] = idx;
  537. }
  538. static uint32_t _get_idx_i(struct idx *idx)
  539. {
  540. if (idx->cur_name == NULL)
  541. return idx->name_base;
  542. return ntohl(*idx->cur_name) + idx->name_base;
  543. }
  544. #define MIDX4_HEADERLEN 12
  545. static PyObject *merge_into(PyObject *self, PyObject *args)
  546. {
  547. PyObject *py_total, *ilist = NULL;
  548. unsigned char *fmap = NULL;
  549. struct sha *sha_ptr, *sha_start = NULL;
  550. uint32_t *table_ptr, *name_ptr, *name_start;
  551. struct idx **idxs = NULL;
  552. Py_ssize_t flen = 0;
  553. int bits = 0, i;
  554. unsigned int total;
  555. uint32_t count, prefix;
  556. int num_i;
  557. int last_i;
  558. if (!PyArg_ParseTuple(args, "w#iOO",
  559. &fmap, &flen, &bits, &py_total, &ilist))
  560. return NULL;
  561. if (!bup_uint_from_py(&total, py_total, "total"))
  562. return NULL;
  563. num_i = PyList_Size(ilist);
  564. idxs = (struct idx **)PyMem_Malloc(num_i * sizeof(struct idx *));
  565. for (i = 0; i < num_i; i++)
  566. {
  567. long len, sha_ofs, name_map_ofs;
  568. idxs[i] = (struct idx *)PyMem_Malloc(sizeof(struct idx));
  569. PyObject *itup = PyList_GetItem(ilist, i);
  570. if (!PyArg_ParseTuple(itup, "t#llli", &idxs[i]->map, &idxs[i]->bytes,
  571. &len, &sha_ofs, &name_map_ofs, &idxs[i]->name_base))
  572. return NULL;
  573. idxs[i]->cur = (struct sha *)&idxs[i]->map[sha_ofs];
  574. idxs[i]->end = &idxs[i]->cur[len];
  575. if (name_map_ofs)
  576. idxs[i]->cur_name = (uint32_t *)&idxs[i]->map[name_map_ofs];
  577. else
  578. idxs[i]->cur_name = NULL;
  579. }
  580. table_ptr = (uint32_t *)&fmap[MIDX4_HEADERLEN];
  581. sha_start = sha_ptr = (struct sha *)&table_ptr[1<<bits];
  582. name_start = name_ptr = (uint32_t *)&sha_ptr[total];
  583. last_i = num_i-1;
  584. count = 0;
  585. prefix = 0;
  586. while (last_i >= 0)
  587. {
  588. struct idx *idx;
  589. uint32_t new_prefix;
  590. if (count % 102424 == 0 && istty2)
  591. fprintf(stderr, "midx: writing %.2f%% (%d/%d)\r",
  592. count*100.0/total, count, total);
  593. idx = idxs[last_i];
  594. new_prefix = _extract_bits((unsigned char *)idx->cur, bits);
  595. while (prefix < new_prefix)
  596. table_ptr[prefix++] = htonl(count);
  597. memcpy(sha_ptr++, idx->cur, sizeof(struct sha));
  598. *name_ptr++ = htonl(_get_idx_i(idx));
  599. ++idx->cur;
  600. if (idx->cur_name != NULL)
  601. ++idx->cur_name;
  602. _fix_idx_order(idxs, &last_i);
  603. ++count;
  604. }
  605. while (prefix < (1<<bits))
  606. table_ptr[prefix++] = htonl(count);
  607. assert(count == total);
  608. assert(prefix == (1<<bits));
  609. assert(sha_ptr == sha_start+count);
  610. assert(name_ptr == name_start+count);
  611. PyMem_Free(idxs);
  612. return PyLong_FromUnsignedLong(count);
  613. }
  614. #define FAN_ENTRIES 256
  615. static PyObject *write_idx(PyObject *self, PyObject *args)
  616. {
  617. char *filename = NULL;
  618. PyObject *py_total, *idx = NULL;
  619. PyObject *part;
  620. unsigned char *fmap = NULL;
  621. Py_ssize_t flen = 0;
  622. unsigned int total = 0;
  623. uint32_t count;
  624. int i, j, ofs64_count;
  625. uint32_t *fan_ptr, *crc_ptr, *ofs_ptr;
  626. uint64_t *ofs64_ptr;
  627. struct sha *sha_ptr;
  628. if (!PyArg_ParseTuple(args, "sw#OO",
  629. &filename, &fmap, &flen, &idx, &py_total))
  630. return NULL;
  631. if (!bup_uint_from_py(&total, py_total, "total"))
  632. return NULL;
  633. if (PyList_Size (idx) != FAN_ENTRIES) // Check for list of the right length.
  634. return PyErr_Format (PyExc_TypeError, "idx must contain %d entries",
  635. FAN_ENTRIES);
  636. const char idx_header[] = "\377tOc\0\0\0\002";
  637. memcpy (fmap, idx_header, sizeof(idx_header) - 1);
  638. fan_ptr = (uint32_t *)&fmap[sizeof(idx_header) - 1];
  639. sha_ptr = (struct sha *)&fan_ptr[FAN_ENTRIES];
  640. crc_ptr = (uint32_t *)&sha_ptr[total];
  641. ofs_ptr = (uint32_t *)&crc_ptr[total];
  642. ofs64_ptr = (uint64_t *)&ofs_ptr[total];
  643. count = 0;
  644. ofs64_count = 0;
  645. for (i = 0; i < FAN_ENTRIES; ++i)
  646. {
  647. int plen;
  648. part = PyList_GET_ITEM(idx, i);
  649. PyList_Sort(part);
  650. plen = PyList_GET_SIZE(part);
  651. count += plen;
  652. *fan_ptr++ = htonl(count);
  653. for (j = 0; j < plen; ++j)
  654. {
  655. unsigned char *sha = NULL;
  656. Py_ssize_t sha_len = 0;
  657. PyObject *crc_py, *ofs_py;
  658. unsigned int crc;
  659. unsigned PY_LONG_LONG ofs_ull;
  660. uint64_t ofs;
  661. if (!PyArg_ParseTuple(PyList_GET_ITEM(part, j), "t#OO",
  662. &sha, &sha_len, &crc_py, &ofs_py))
  663. return NULL;
  664. if(!bup_uint_from_py(&crc, crc_py, "crc"))
  665. return NULL;
  666. if(!bup_ullong_from_py(&ofs_ull, ofs_py, "ofs"))
  667. return NULL;
  668. assert(crc <= UINT32_MAX);
  669. assert(ofs_ull <= UINT64_MAX);
  670. ofs = ofs_ull;
  671. if (sha_len != sizeof(struct sha))
  672. return NULL;
  673. memcpy(sha_ptr++, sha, sizeof(struct sha));
  674. *crc_ptr++ = htonl(crc);
  675. if (ofs > 0x7fffffff)
  676. {
  677. *ofs64_ptr++ = htonll(ofs);
  678. ofs = 0x80000000 | ofs64_count++;
  679. }
  680. *ofs_ptr++ = htonl((uint32_t)ofs);
  681. }
  682. }
  683. int rc = msync(fmap, flen, MS_ASYNC);
  684. if (rc != 0)
  685. return PyErr_SetFromErrnoWithFilename(PyExc_IOError, filename);
  686. return PyLong_FromUnsignedLong(count);
  687. }
  688. // I would have made this a lower-level function that just fills in a buffer
  689. // with random values, and then written those values from python. But that's
  690. // about 20% slower in my tests, and since we typically generate random
  691. // numbers for benchmarking other parts of bup, any slowness in generating
  692. // random bytes will make our benchmarks inaccurate. Plus nobody wants
  693. // pseudorandom bytes much except for this anyway.
  694. static PyObject *write_random(PyObject *self, PyObject *args)
  695. {
  696. uint32_t buf[1024/4];
  697. int fd = -1, seed = 0, verbose = 0;
  698. ssize_t ret;
  699. long long len = 0, kbytes = 0, written = 0;
  700. if (!PyArg_ParseTuple(args, "iLii", &fd, &len, &seed, &verbose))
  701. return NULL;
  702. srandom(seed);
  703. for (kbytes = 0; kbytes < len/1024; kbytes++)
  704. {
  705. unsigned i;
  706. for (i = 0; i < sizeof(buf)/sizeof(buf[0]); i++)
  707. buf[i] = random();
  708. ret = write(fd, buf, sizeof(buf));
  709. if (ret < 0)
  710. ret = 0;
  711. written += ret;
  712. if (ret < (int)sizeof(buf))
  713. break;
  714. if (verbose && kbytes/1024 > 0 && !(kbytes%1024))
  715. fprintf(stderr, "Random: %lld Mbytes\r", kbytes/1024);
  716. }
  717. // handle non-multiples of 1024
  718. if (len % 1024)
  719. {
  720. unsigned i;
  721. for (i = 0; i < sizeof(buf)/sizeof(buf[0]); i++)
  722. buf[i] = random();
  723. ret = write(fd, buf, len % 1024);
  724. if (ret < 0)
  725. ret = 0;
  726. written += ret;
  727. }
  728. if (kbytes/1024 > 0)
  729. fprintf(stderr, "Random: %lld Mbytes, done.\n", kbytes/1024);
  730. return Py_BuildValue("L", written);
  731. }
  732. static PyObject *random_sha(PyObject *self, PyObject *args)
  733. {
  734. static int seeded = 0;
  735. uint32_t shabuf[20/4];
  736. int i;
  737. if (!seeded)
  738. {
  739. assert(sizeof(shabuf) == 20);
  740. srandom(time(NULL));
  741. seeded = 1;
  742. }
  743. if (!PyArg_ParseTuple(args, ""))
  744. return NULL;
  745. memset(shabuf, 0, sizeof(shabuf));
  746. for (i=0; i < 20/4; i++)
  747. shabuf[i] = random();
  748. return Py_BuildValue("s#", shabuf, 20);
  749. }
  750. static int _open_noatime(const char *filename, int attrs)
  751. {
  752. int attrs_noatime, fd;
  753. attrs |= O_RDONLY;
  754. #ifdef O_NOFOLLOW
  755. attrs |= O_NOFOLLOW;
  756. #endif
  757. #ifdef O_LARGEFILE
  758. attrs |= O_LARGEFILE;
  759. #endif
  760. attrs_noatime = attrs;
  761. #ifdef O_NOATIME
  762. attrs_noatime |= O_NOATIME;
  763. #endif
  764. fd = open(filename, attrs_noatime);
  765. if (fd < 0 && errno == EPERM)
  766. {
  767. // older Linux kernels would return EPERM if you used O_NOATIME
  768. // and weren't the file's owner. This pointless restriction was
  769. // relaxed eventually, but we have to handle it anyway.
  770. // (VERY old kernels didn't recognized O_NOATIME, but they would
  771. // just harmlessly ignore it, so this branch won't trigger)
  772. fd = open(filename, attrs);
  773. }
  774. return fd;
  775. }
  776. static PyObject *open_noatime(PyObject *self, PyObject *args)
  777. {
  778. char *filename = NULL;
  779. int fd;
  780. if (!PyArg_ParseTuple(args, "s", &filename))
  781. return NULL;
  782. fd = _open_noatime(filename, 0);
  783. if (fd < 0)
  784. return PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename);
  785. return Py_BuildValue("i", fd);
  786. }
  787. static PyObject *fadvise_done(PyObject *self, PyObject *args)
  788. {
  789. int fd = -1;
  790. long long ofs = 0;
  791. if (!PyArg_ParseTuple(args, "iL", &fd, &ofs))
  792. return NULL;
  793. #ifdef POSIX_FADV_DONTNEED
  794. posix_fadvise(fd, 0, ofs, POSIX_FADV_DONTNEED);
  795. #endif
  796. return Py_BuildValue("");
  797. }
  798. // Currently the Linux kernel and FUSE disagree over the type for
  799. // FS_IOC_GETFLAGS and FS_IOC_SETFLAGS. The kernel actually uses int,
  800. // but FUSE chose long (matching the declaration in linux/fs.h). So
  801. // if you use int, and then traverse a FUSE filesystem, you may
  802. // corrupt the stack. But if you use long, then you may get invalid
  803. // results on big-endian systems.
  804. //
  805. // For now, we just use long, and then disable Linux attrs entirely
  806. // (with a warning) in helpers.py on systems that are affected.
  807. #ifdef BUP_HAVE_FILE_ATTRS
  808. static PyObject *bup_get_linux_file_attr(PyObject *self, PyObject *args)
  809. {
  810. int rc;
  811. unsigned long attr;
  812. char *path;
  813. int fd;
  814. if (!PyArg_ParseTuple(args, "s", &path))
  815. return NULL;
  816. fd = _open_noatime(path, O_NONBLOCK);
  817. if (fd == -1)
  818. return PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
  819. attr = 0; // Handle int/long mismatch (see above)
  820. rc = ioctl(fd, FS_IOC_GETFLAGS, &attr);
  821. if (rc == -1)
  822. {
  823. close(fd);
  824. return PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
  825. }
  826. close(fd);
  827. assert(attr <= UINT_MAX); // Kernel type is actually int
  828. return PyLong_FromUnsignedLong(attr);
  829. }
  830. #endif /* def BUP_HAVE_FILE_ATTRS */
  831. #ifdef BUP_HAVE_FILE_ATTRS
  832. static PyObject *bup_set_linux_file_attr(PyObject *self, PyObject *args)
  833. {
  834. int rc;
  835. unsigned long orig_attr;
  836. unsigned int attr;
  837. char *path;
  838. PyObject *py_attr;
  839. int fd;
  840. if (!PyArg_ParseTuple(args, "sO", &path, &py_attr))
  841. return NULL;
  842. if (!bup_uint_from_py(&attr, py_attr, "attr"))
  843. return NULL;
  844. fd = open(path, O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_NOFOLLOW);
  845. if (fd == -1)
  846. return PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
  847. // Restrict attr to modifiable flags acdeijstuADST -- see
  848. // chattr(1) and the e2fsprogs source. Letter to flag mapping is
  849. // in pf.c flags_array[].
  850. attr &= FS_APPEND_FL | FS_COMPR_FL | FS_NODUMP_FL | FS_EXTENT_FL
  851. | FS_IMMUTABLE_FL | FS_JOURNAL_DATA_FL | FS_SECRM_FL | FS_NOTAIL_FL
  852. | FS_UNRM_FL | FS_NOATIME_FL | FS_DIRSYNC_FL | FS_SYNC_FL
  853. | FS_TOPDIR_FL | FS_NOCOW_FL;
  854. // The extents flag can't be removed, so don't (see chattr(1) and chattr.c).
  855. orig_attr = 0; // Handle int/long mismatch (see above)
  856. rc = ioctl(fd, FS_IOC_GETFLAGS, &orig_attr);
  857. assert(orig_attr <= UINT_MAX); // Kernel type is actually int
  858. if (rc == -1)
  859. {
  860. close(fd);
  861. return PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
  862. }
  863. attr |= ((unsigned int) orig_attr) & FS_EXTENT_FL;
  864. rc = ioctl(fd, FS_IOC_SETFLAGS, &attr);
  865. if (rc == -1)
  866. {
  867. close(fd);
  868. return PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
  869. }
  870. close(fd);
  871. return Py_BuildValue("O", Py_None);
  872. }
  873. #endif /* def BUP_HAVE_FILE_ATTRS */
  874. #ifndef HAVE_UTIMENSAT
  875. #ifndef HAVE_UTIMES
  876. #error "cannot find utimensat or utimes()"
  877. #endif
  878. #ifndef HAVE_LUTIMES
  879. #error "cannot find utimensat or lutimes()"
  880. #endif
  881. #endif
  882. #define ASSIGN_PYLONG_TO_INTEGRAL(dest, pylong, overflow) \
  883. ({ \
  884. int result = 0; \
  885. *(overflow) = 0; \
  886. const long long lltmp = PyLong_AsLongLong(pylong); \
  887. if (lltmp == -1 && PyErr_Occurred()) \
  888. { \
  889. if (PyErr_ExceptionMatches(PyExc_OverflowError)) \
  890. { \
  891. const unsigned long long ulltmp = PyLong_AsUnsignedLongLong(pylong); \
  892. if (ulltmp == (unsigned long long) -1 && PyErr_Occurred()) \
  893. { \
  894. if (PyErr_ExceptionMatches(PyExc_OverflowError)) \
  895. { \
  896. PyErr_Clear(); \
  897. *(overflow) = 1; \
  898. } \
  899. } \
  900. if (INTEGRAL_ASSIGNMENT_FITS((dest), ulltmp)) \
  901. result = 1; \
  902. else \
  903. *(overflow) = 1; \
  904. } \
  905. } \
  906. else \
  907. { \
  908. if (INTEGRAL_ASSIGNMENT_FITS((dest), lltmp)) \
  909. result = 1; \
  910. else \
  911. *(overflow) = 1; \
  912. } \
  913. result; \
  914. })
  915. #ifdef HAVE_UTIMENSAT
  916. static PyObject *bup_utimensat(PyObject *self, PyObject *args)
  917. {
  918. int rc;
  919. int fd, flag;
  920. char *path;
  921. PyObject *access_py, *modification_py;
  922. struct timespec ts[2];
  923. if (!PyArg_ParseTuple(args, "is((Ol)(Ol))i",
  924. &fd,
  925. &path,
  926. &access_py, &(ts[0].tv_nsec),
  927. &modification_py, &(ts[1].tv_nsec),
  928. &flag))
  929. return NULL;
  930. int overflow;
  931. if (!ASSIGN_PYLONG_TO_INTEGRAL(&(ts[0].tv_sec), access_py, &overflow))
  932. {
  933. if (overflow)
  934. PyErr_SetString(PyExc_ValueError,
  935. "unable to convert access time seconds for utimensat");
  936. return NULL;
  937. }
  938. if (!ASSIGN_PYLONG_TO_INTEGRAL(&(ts[1].tv_sec), modification_py, &overflow))
  939. {
  940. if (overflow)
  941. PyErr_SetString(PyExc_ValueError,
  942. "unable to convert modification time seconds for utimensat");
  943. return NULL;
  944. }
  945. rc = utimensat(fd, path, ts, flag);
  946. if (rc != 0)
  947. return PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
  948. return Py_BuildValue("O", Py_None);
  949. }
  950. #endif /* def HAVE_UTIMENSAT */
  951. #if defined(HAVE_UTIMES) || defined(HAVE_LUTIMES)
  952. static int bup_parse_xutimes_args(char **path,
  953. struct timeval tv[2],
  954. PyObject *args)
  955. {
  956. PyObject *access_py, *modification_py;
  957. long long access_us, modification_us; // POSIX guarantees tv_usec is signed.
  958. if (!PyArg_ParseTuple(args, "s((OL)(OL))",
  959. path,
  960. &access_py, &access_us,
  961. &modification_py, &modification_us))
  962. return 0;
  963. int overflow;
  964. if (!ASSIGN_PYLONG_TO_INTEGRAL(&(tv[0].tv_sec), access_py, &overflow))
  965. {
  966. if (overflow)
  967. PyErr_SetString(PyExc_ValueError, "unable to convert access time seconds to timeval");
  968. return 0;
  969. }
  970. if (!INTEGRAL_ASSIGNMENT_FITS(&(tv[0].tv_usec), access_us))
  971. {
  972. PyErr_SetString(PyExc_ValueError, "unable to convert access time nanoseconds to timeval");
  973. return 0;
  974. }
  975. if (!ASSIGN_PYLONG_TO_INTEGRAL(&(tv[1].tv_sec), modification_py, &overflow))
  976. {
  977. if (overflow)
  978. PyErr_SetString(PyExc_ValueError, "unable to convert modification time seconds to timeval");
  979. return 0;
  980. }
  981. if (!INTEGRAL_ASSIGNMENT_FITS(&(tv[1].tv_usec), modification_us))
  982. {
  983. PyErr_SetString(PyExc_ValueError, "unable to convert modification time nanoseconds to timeval");
  984. return 0;
  985. }
  986. return 1;
  987. }
  988. #endif /* defined(HAVE_UTIMES) || defined(HAVE_LUTIMES) */
  989. #ifdef HAVE_UTIMES
  990. static PyObject *bup_utimes(PyObject *self, PyObject *args)
  991. {
  992. char *path;
  993. struct timeval tv[2];
  994. if (!bup_parse_xutimes_args(&path, tv, args))
  995. return NULL;
  996. int rc = utimes(path, tv);
  997. if (rc != 0)
  998. return PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
  999. return Py_BuildValue("O", Py_None);
  1000. }
  1001. #endif /* def HAVE_UTIMES */
  1002. #ifdef HAVE_LUTIMES
  1003. static PyObject *bup_lutimes(PyObject *self, PyObject *args)
  1004. {
  1005. char *path;
  1006. struct timeval tv[2];
  1007. if (!bup_parse_xutimes_args(&path, tv, args))
  1008. return NULL;
  1009. int rc = lutimes(path, tv);
  1010. if (rc != 0)
  1011. return PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
  1012. return Py_BuildValue("O", Py_None);
  1013. }
  1014. #endif /* def HAVE_LUTIMES */
  1015. #ifdef HAVE_STAT_ST_ATIM
  1016. # define BUP_STAT_ATIME_NS(st) (st)->st_atim.tv_nsec
  1017. # define BUP_STAT_MTIME_NS(st) (st)->st_mtim.tv_nsec
  1018. # define BUP_STAT_CTIME_NS(st) (st)->st_ctim.tv_nsec
  1019. #elif defined HAVE_STAT_ST_ATIMENSEC
  1020. # define BUP_STAT_ATIME_NS(st) (st)->st_atimespec.tv_nsec
  1021. # define BUP_STAT_MTIME_NS(st) (st)->st_mtimespec.tv_nsec
  1022. # define BUP_STAT_CTIME_NS(st) (st)->st_ctimespec.tv_nsec
  1023. #else
  1024. # define BUP_STAT_ATIME_NS(st) 0
  1025. # define BUP_STAT_MTIME_NS(st) 0
  1026. # define BUP_STAT_CTIME_NS(st) 0
  1027. #endif
  1028. #pragma clang diagnostic push
  1029. #pragma clang diagnostic ignored "-Wtautological-compare" // For INTEGER_TO_PY().
  1030. static PyObject *stat_struct_to_py(const struct stat *st,
  1031. const char *filename,
  1032. int fd)
  1033. {
  1034. // We can check the known (via POSIX) signed and unsigned types at
  1035. // compile time, but not (easily) the unspecified types, so handle
  1036. // those via INTEGER_TO_PY(). Assumes ns values will fit in a
  1037. // long.
  1038. return Py_BuildValue("OKOOOOOL(Ol)(Ol)(Ol)",
  1039. INTEGER_TO_PY(st->st_mode),
  1040. (unsigned PY_LONG_LONG) st->st_ino,
  1041. INTEGER_TO_PY(st->st_dev),
  1042. INTEGER_TO_PY(st->st_nlink),
  1043. INTEGER_TO_PY(st->st_uid),
  1044. INTEGER_TO_PY(st->st_gid),
  1045. INTEGER_TO_PY(st->st_rdev),
  1046. (PY_LONG_LONG) st->st_size,
  1047. INTEGER_TO_PY(st->st_atime),
  1048. (long) BUP_STAT_ATIME_NS(st),
  1049. INTEGER_TO_PY(st->st_mtime),
  1050. (long) BUP_STAT_MTIME_NS(st),
  1051. INTEGER_TO_PY(st->st_ctime),
  1052. (long) BUP_STAT_CTIME_NS(st));
  1053. }
  1054. #pragma clang diagnostic pop // ignored "-Wtautological-compare"
  1055. static PyObject *bup_stat(PyObject *self, PyObject *args)
  1056. {
  1057. int rc;
  1058. char *filename;
  1059. if (!PyArg_ParseTuple(args, "s", &filename))
  1060. return NULL;
  1061. struct stat st;
  1062. rc = stat(filename, &st);
  1063. if (rc != 0)
  1064. return PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename);
  1065. return stat_struct_to_py(&st, filename, 0);
  1066. }
  1067. static PyObject *bup_lstat(PyObject *self, PyObject *args)
  1068. {
  1069. int rc;
  1070. char *filename;
  1071. if (!PyArg_ParseTuple(args, "s", &filename))
  1072. return NULL;
  1073. struct stat st;
  1074. rc = lstat(filename, &st);
  1075. if (rc != 0)
  1076. return PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename);
  1077. return stat_struct_to_py(&st, filename, 0);
  1078. }
  1079. static PyObject *bup_fstat(PyObject *self, PyObject *args)
  1080. {
  1081. int rc, fd;
  1082. if (!PyArg_ParseTuple(args, "i", &fd))
  1083. return NULL;
  1084. struct stat st;
  1085. rc = fstat(fd, &st);
  1086. if (rc != 0)
  1087. return PyErr_SetFromErrno(PyExc_OSError);
  1088. return stat_struct_to_py(&st, NULL, fd);
  1089. }
  1090. static PyMethodDef helper_methods[] = {
  1091. { "write_sparsely", bup_write_sparsely, METH_VARARGS,
  1092. "Write buf excepting zeros at the end. Return trailing zero count." },
  1093. { "selftest", selftest, METH_VARARGS,
  1094. "Check that the rolling checksum rolls correctly (for unit tests)." },
  1095. { "blobbits", blobbits, METH_VARARGS,
  1096. "Return the number of bits in the rolling checksum." },
  1097. { "splitbuf", splitbuf, METH_VARARGS,
  1098. "Split a list of strings based on a rolling checksum." },
  1099. { "bitmatch", bitmatch, METH_VARARGS,
  1100. "Count the number of matching prefix bits between two strings." },
  1101. { "firstword", firstword, METH_VARARGS,
  1102. "Return an int corresponding to the first 32 bits of buf." },
  1103. { "bloom_contains", bloom_contains, METH_VARARGS,
  1104. "Check if a bloom filter of 2^nbits bytes contains an object" },
  1105. { "bloom_add", bloom_add, METH_VARARGS,
  1106. "Add an object to a bloom filter of 2^nbits bytes" },
  1107. { "extract_bits", extract_bits, METH_VARARGS,
  1108. "Take the first 'nbits' bits from 'buf' and return them as an int." },
  1109. { "merge_into", merge_into, METH_VARARGS,
  1110. "Merges a bunch of idx and midx files into a single midx." },
  1111. { "write_idx", write_idx, METH_VARARGS,
  1112. "Write a PackIdxV2 file from an idx list of lists of tuples" },
  1113. { "write_random", write_random, METH_VARARGS,
  1114. "Write random bytes to the given file descriptor" },
  1115. { "random_sha", random_sha, METH_VARARGS,
  1116. "Return a random 20-byte string" },
  1117. { "open_noatime", open_noatime, METH_VARARGS,
  1118. "open() the given filename for read with O_NOATIME if possible" },
  1119. { "fadvise_done", fadvise_done, METH_VARARGS,
  1120. "Inform the kernel that we're finished with earlier parts of a file" },
  1121. #ifdef BUP_HAVE_FILE_ATTRS
  1122. { "get_linux_file_attr", bup_get_linux_file_attr, METH_VARARGS,
  1123. "Return the Linux attributes for the given file." },
  1124. #endif
  1125. #ifdef BUP_HAVE_FILE_ATTRS
  1126. { "set_linux_file_attr", bup_set_linux_file_attr, METH_VARARGS,
  1127. "Set the Linux attributes for the given file." },
  1128. #endif
  1129. #ifdef HAVE_UTIMENSAT
  1130. { "bup_utimensat", bup_utimensat, METH_VARARGS,
  1131. "Change path timestamps with nanosecond precision (POSIX)." },
  1132. #endif
  1133. #ifdef HAVE_UTIMES
  1134. { "bup_utimes", bup_utimes, METH_VARARGS,
  1135. "Change path timestamps with microsecond precision." },
  1136. #endif
  1137. #ifdef HAVE_LUTIMES
  1138. { "bup_lutimes", bup_lutimes, METH_VARARGS,
  1139. "Change path timestamps with microsecond precision;"
  1140. " don't follow symlinks." },
  1141. #endif
  1142. { "stat", bup_stat, METH_VARARGS,
  1143. "Extended version of stat." },
  1144. { "lstat", bup_lstat, METH_VARARGS,
  1145. "Extended version of lstat." },
  1146. { "fstat", bup_fstat, METH_VARARGS,
  1147. "Extended version of fstat." },
  1148. { NULL, NULL, 0, NULL }, // sentinel
  1149. };
  1150. PyMODINIT_FUNC init_helpers(void)
  1151. {
  1152. // FIXME: migrate these tests to configure. Check against the
  1153. // type we're going to use when passing to python. Other stat
  1154. // types are tested at runtime.
  1155. assert(sizeof(ino_t) <= sizeof(unsigned PY_LONG_LONG));
  1156. assert(sizeof(off_t) <= sizeof(PY_LONG_LONG));
  1157. assert(sizeof(blksize_t) <= sizeof(PY_LONG_LONG));
  1158. assert(sizeof(blkcnt_t) <= sizeof(PY_LONG_LONG));
  1159. // Just be sure (relevant when passing timestamps back to Python above).
  1160. assert(sizeof(PY_LONG_LONG) <= sizeof(long long));
  1161. assert(sizeof(unsigned PY_LONG_LONG) <= sizeof(unsigned long long));
  1162. char *e;
  1163. PyObject *m = Py_InitModule("_helpers", helper_methods);
  1164. if (m == NULL)
  1165. return;
  1166. #pragma clang diagnostic push
  1167. #pragma clang diagnostic ignored "-Wtautological-compare" // For INTEGER_TO_PY().
  1168. #ifdef HAVE_UTIMENSAT
  1169. {
  1170. PyObject *value;
  1171. value = INTEGER_TO_PY(AT_FDCWD);
  1172. PyObject_SetAttrString(m, "AT_FDCWD", value);
  1173. Py_DECREF(value);
  1174. value = INTEGER_TO_PY(AT_SYMLINK_NOFOLLOW);
  1175. PyObject_SetAttrString(m, "AT_SYMLINK_NOFOLLOW", value);
  1176. Py_DECREF(value);
  1177. value = INTEGER_TO_PY(UTIME_NOW);
  1178. PyObject_SetAttrString(m, "UTIME_NOW", value);
  1179. Py_DECREF(value);
  1180. }
  1181. #endif
  1182. {
  1183. PyObject *value;
  1184. const long arg_max = sysconf(_SC_ARG_MAX);
  1185. if (arg_max == -1)
  1186. {
  1187. fprintf(stderr, "Cannot find SC_ARG_MAX, please report a bug.\n");
  1188. exit(1);
  1189. }
  1190. value = INTEGER_TO_PY(arg_max);
  1191. PyObject_SetAttrString(m, "SC_ARG_MAX", value);
  1192. Py_DECREF(value);
  1193. }
  1194. #pragma clang diagnostic pop // ignored "-Wtautological-compare"
  1195. e = getenv("BUP_FORCE_TTY");
  1196. istty2 = isatty(2) || (atoi(e ? e : "0") & 2);
  1197. unpythonize_argv();
  1198. }