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