]> arthur.barton.de Git - bup.git/blob - lib/bup/_helpers.c
f58243017f029f9ba821a8e0205c4f7fca9cbbc1
[bup.git] / lib / bup / _helpers.c
1 #define _LARGEFILE64_SOURCE 1
2 #undef NDEBUG
3 #include "../../config/config.h"
4 #include "bupsplit.h"
5 #include <Python.h>
6 #include <assert.h>
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <arpa/inet.h>
10 #include <stdint.h>
11 #include <stdlib.h>
12 #include <stdio.h>
13
14 #ifdef HAVE_SYS_TYPES_H
15 #include <sys/types.h>
16 #endif
17 #ifdef HAVE_SYS_STAT_H
18 #include <sys/stat.h>
19 #endif
20 #ifdef HAVE_UNISTD_H
21 #include <unistd.h>
22 #endif
23
24 #ifdef HAVE_LINUX_FS_H
25 #include <linux/fs.h>
26 #endif
27 #ifdef HAVE_SYS_IOCTL_H
28 #include <sys/ioctl.h>
29 #endif
30
31 static int istty2 = 0;
32
33 // Probably we should use autoconf or something and set HAVE_PY_GETARGCARGV...
34 #if __WIN32__ || __CYGWIN__
35
36 // There's no 'ps' on win32 anyway, and Py_GetArgcArgv() isn't available.
37 static void unpythonize_argv(void) { }
38
39 #else // not __WIN32__
40
41 // For some reason this isn't declared in Python.h
42 extern void Py_GetArgcArgv(int *argc, char ***argv);
43
44 static void unpythonize_argv(void)
45 {
46     int argc, i;
47     char **argv, *arge;
48     
49     Py_GetArgcArgv(&argc, &argv);
50     
51     for (i = 0; i < argc-1; i++)
52     {
53         if (argv[i] + strlen(argv[i]) + 1 != argv[i+1])
54         {
55             // The argv block doesn't work the way we expected; it's unsafe
56             // to mess with it.
57             return;
58         }
59     }
60     
61     arge = argv[argc-1] + strlen(argv[argc-1]) + 1;
62     
63     if (strstr(argv[0], "python") && argv[1] == argv[0] + strlen(argv[0]) + 1)
64     {
65         char *p;
66         size_t len, diff;
67         p = strrchr(argv[1], '/');
68         if (p)
69         {
70             p++;
71             diff = p - argv[0];
72             len = arge - p;
73             memmove(argv[0], p, len);
74             memset(arge - diff, 0, diff);
75             for (i = 0; i < argc; i++)
76                 argv[i] = argv[i+1] ? argv[i+1]-diff : NULL;
77         }
78     }
79 }
80
81 #endif // not __WIN32__ or __CYGWIN__
82
83
84 static PyObject *selftest(PyObject *self, PyObject *args)
85 {
86     if (!PyArg_ParseTuple(args, ""))
87         return NULL;
88     
89     return Py_BuildValue("i", !bupsplit_selftest());
90 }
91
92
93 static PyObject *blobbits(PyObject *self, PyObject *args)
94 {
95     if (!PyArg_ParseTuple(args, ""))
96         return NULL;
97     return Py_BuildValue("i", BUP_BLOBBITS);
98 }
99
100
101 static PyObject *splitbuf(PyObject *self, PyObject *args)
102 {
103     unsigned char *buf = NULL;
104     int len = 0, out = 0, bits = -1;
105
106     if (!PyArg_ParseTuple(args, "t#", &buf, &len))
107         return NULL;
108     out = bupsplit_find_ofs(buf, len, &bits);
109     if (out) assert(bits >= BUP_BLOBBITS);
110     return Py_BuildValue("ii", out, bits);
111 }
112
113
114 static PyObject *bitmatch(PyObject *self, PyObject *args)
115 {
116     unsigned char *buf1 = NULL, *buf2 = NULL;
117     int len1 = 0, len2 = 0;
118     int byte, bit;
119
120     if (!PyArg_ParseTuple(args, "t#t#", &buf1, &len1, &buf2, &len2))
121         return NULL;
122     
123     bit = 0;
124     for (byte = 0; byte < len1 && byte < len2; byte++)
125     {
126         int b1 = buf1[byte], b2 = buf2[byte];
127         if (b1 != b2)
128         {
129             for (bit = 0; bit < 8; bit++)
130                 if ( (b1 & (0x80 >> bit)) != (b2 & (0x80 >> bit)) )
131                     break;
132             break;
133         }
134     }
135     
136     return Py_BuildValue("i", byte*8 + bit);
137 }
138
139
140 static PyObject *firstword(PyObject *self, PyObject *args)
141 {
142     unsigned char *buf = NULL;
143     int len = 0;
144     uint32_t v;
145
146     if (!PyArg_ParseTuple(args, "t#", &buf, &len))
147         return NULL;
148     
149     if (len < 4)
150         return NULL;
151     
152     v = ntohl(*(uint32_t *)buf);
153     return PyLong_FromUnsignedLong(v);
154 }
155
156
157 #define BLOOM2_HEADERLEN 16
158
159 typedef struct {
160     uint32_t high;
161     unsigned char low;
162 } bits40_t;
163
164 static void to_bloom_address_bitmask4(const bits40_t *buf,
165         const int nbits, uint64_t *v, unsigned char *bitmask)
166 {
167     int bit;
168     uint64_t raw, mask;
169
170     mask = (1<<nbits) - 1;
171     raw = (((uint64_t)ntohl(buf->high)) << 8) | buf->low;
172     bit = (raw >> (37-nbits)) & 0x7;
173     *v = (raw >> (40-nbits)) & mask;
174     *bitmask = 1 << bit;
175 }
176
177 static void to_bloom_address_bitmask5(const uint32_t *buf,
178         const int nbits, uint32_t *v, unsigned char *bitmask)
179 {
180     int bit;
181     uint32_t raw, mask;
182
183     mask = (1<<nbits) - 1;
184     raw = ntohl(*buf);
185     bit = (raw >> (29-nbits)) & 0x7;
186     *v = (raw >> (32-nbits)) & mask;
187     *bitmask = 1 << bit;
188 }
189
190 #define BLOOM_SET_BIT(name, address, itype, otype) \
191 static void name(unsigned char *bloom, const void *buf, const int nbits)\
192 {\
193     unsigned char bitmask;\
194     otype v;\
195     address((itype *)buf, nbits, &v, &bitmask);\
196     bloom[BLOOM2_HEADERLEN+v] |= bitmask;\
197 }
198 BLOOM_SET_BIT(bloom_set_bit4, to_bloom_address_bitmask4, bits40_t, uint64_t)
199 BLOOM_SET_BIT(bloom_set_bit5, to_bloom_address_bitmask5, uint32_t, uint32_t)
200
201
202 #define BLOOM_GET_BIT(name, address, itype, otype) \
203 static int name(const unsigned char *bloom, const void *buf, const int nbits)\
204 {\
205     unsigned char bitmask;\
206     otype v;\
207     address((itype *)buf, nbits, &v, &bitmask);\
208     return bloom[BLOOM2_HEADERLEN+v] & bitmask;\
209 }
210 BLOOM_GET_BIT(bloom_get_bit4, to_bloom_address_bitmask4, bits40_t, uint64_t)
211 BLOOM_GET_BIT(bloom_get_bit5, to_bloom_address_bitmask5, uint32_t, uint32_t)
212
213
214 static PyObject *bloom_add(PyObject *self, PyObject *args)
215 {
216     unsigned char *sha = NULL, *bloom = NULL;
217     unsigned char *end;
218     int len = 0, blen = 0, nbits = 0, k = 0;
219
220     if (!PyArg_ParseTuple(args, "w#s#ii", &bloom, &blen, &sha, &len, &nbits, &k))
221         return NULL;
222
223     if (blen < 16+(1<<nbits) || len % 20 != 0)
224         return NULL;
225
226     if (k == 5)
227     {
228         if (nbits > 29)
229             return NULL;
230         for (end = sha + len; sha < end; sha += 20/k)
231             bloom_set_bit5(bloom, sha, nbits);
232     }
233     else if (k == 4)
234     {
235         if (nbits > 37)
236             return NULL;
237         for (end = sha + len; sha < end; sha += 20/k)
238             bloom_set_bit4(bloom, sha, nbits);
239     }
240     else
241         return NULL;
242
243
244     return Py_BuildValue("i", len/20);
245 }
246
247 static PyObject *bloom_contains(PyObject *self, PyObject *args)
248 {
249     unsigned char *sha = NULL, *bloom = NULL;
250     int len = 0, blen = 0, nbits = 0, k = 0;
251     unsigned char *end;
252     int steps;
253
254     if (!PyArg_ParseTuple(args, "t#s#ii", &bloom, &blen, &sha, &len, &nbits, &k))
255         return NULL;
256
257     if (len != 20)
258         return NULL;
259
260     if (k == 5)
261     {
262         if (nbits > 29)
263             return NULL;
264         for (steps = 1, end = sha + 20; sha < end; sha += 20/k, steps++)
265             if (!bloom_get_bit5(bloom, sha, nbits))
266                 return Py_BuildValue("Oi", Py_None, steps);
267     }
268     else if (k == 4)
269     {
270         if (nbits > 37)
271             return NULL;
272         for (steps = 1, end = sha + 20; sha < end; sha += 20/k, steps++)
273             if (!bloom_get_bit4(bloom, sha, nbits))
274                 return Py_BuildValue("Oi", Py_None, steps);
275     }
276     else
277         return NULL;
278
279     return Py_BuildValue("ii", 1, k);
280 }
281
282
283 static uint32_t _extract_bits(unsigned char *buf, int nbits)
284 {
285     uint32_t v, mask;
286
287     mask = (1<<nbits) - 1;
288     v = ntohl(*(uint32_t *)buf);
289     v = (v >> (32-nbits)) & mask;
290     return v;
291 }
292 static PyObject *extract_bits(PyObject *self, PyObject *args)
293 {
294     unsigned char *buf = NULL;
295     int len = 0, nbits = 0;
296
297     if (!PyArg_ParseTuple(args, "t#i", &buf, &len, &nbits))
298         return NULL;
299     
300     if (len < 4)
301         return NULL;
302     
303     return PyLong_FromUnsignedLong(_extract_bits(buf, nbits));
304 }
305
306
307 struct sha {
308     unsigned char bytes[20];
309 };
310 struct idx {
311     unsigned char *map;
312     struct sha *cur;
313     struct sha *end;
314     uint32_t *cur_name;
315     long bytes;
316     int name_base;
317 };
318
319
320 static int _cmp_sha(const struct sha *sha1, const struct sha *sha2)
321 {
322     int i;
323     for (i = 0; i < sizeof(struct sha); i++)
324         if (sha1->bytes[i] != sha2->bytes[i])
325             return sha1->bytes[i] - sha2->bytes[i];
326     return 0;
327 }
328
329
330 static void _fix_idx_order(struct idx **idxs, int *last_i)
331 {
332     struct idx *idx;
333     int low, mid, high, c = 0;
334
335     idx = idxs[*last_i];
336     if (idxs[*last_i]->cur >= idxs[*last_i]->end)
337     {
338         idxs[*last_i] = NULL;
339         PyMem_Free(idx);
340         --*last_i;
341         return;
342     }
343     if (*last_i == 0)
344         return;
345
346     low = *last_i-1;
347     mid = *last_i;
348     high = 0;
349     while (low >= high)
350     {
351         mid = (low + high) / 2;
352         c = _cmp_sha(idx->cur, idxs[mid]->cur);
353         if (c < 0)
354             high = mid + 1;
355         else if (c > 0)
356             low = mid - 1;
357         else
358             break;
359     }
360     if (c < 0)
361         ++mid;
362     if (mid == *last_i)
363         return;
364     memmove(&idxs[mid+1], &idxs[mid], (*last_i-mid)*sizeof(struct idx *));
365     idxs[mid] = idx;
366 }
367
368
369 static uint32_t _get_idx_i(struct idx *idx)
370 {
371     if (idx->cur_name == NULL)
372         return idx->name_base;
373     return ntohl(*idx->cur_name) + idx->name_base;
374 }
375
376 #define MIDX4_HEADERLEN 12
377
378 static PyObject *merge_into(PyObject *self, PyObject *args)
379 {
380     PyObject *ilist = NULL;
381     unsigned char *fmap = NULL;
382     struct sha *sha_ptr, *sha_start = NULL;
383     uint32_t *table_ptr, *name_ptr, *name_start;
384     struct idx **idxs = NULL;
385     int flen = 0, bits = 0, i;
386     uint32_t total, count, prefix;
387     int num_i;
388     int last_i;
389
390     if (!PyArg_ParseTuple(args, "w#iIO", &fmap, &flen, &bits, &total, &ilist))
391         return NULL;
392
393     num_i = PyList_Size(ilist);
394     idxs = (struct idx **)PyMem_Malloc(num_i * sizeof(struct idx *));
395
396     for (i = 0; i < num_i; i++)
397     {
398         long len, sha_ofs, name_map_ofs;
399         idxs[i] = (struct idx *)PyMem_Malloc(sizeof(struct idx));
400         PyObject *itup = PyList_GetItem(ilist, i);
401         if (!PyArg_ParseTuple(itup, "t#llli", &idxs[i]->map, &idxs[i]->bytes,
402                     &len, &sha_ofs, &name_map_ofs, &idxs[i]->name_base))
403             return NULL;
404         idxs[i]->cur = (struct sha *)&idxs[i]->map[sha_ofs];
405         idxs[i]->end = &idxs[i]->cur[len];
406         if (name_map_ofs)
407             idxs[i]->cur_name = (uint32_t *)&idxs[i]->map[name_map_ofs];
408         else
409             idxs[i]->cur_name = NULL;
410     }
411     table_ptr = (uint32_t *)&fmap[MIDX4_HEADERLEN];
412     sha_start = sha_ptr = (struct sha *)&table_ptr[1<<bits];
413     name_start = name_ptr = (uint32_t *)&sha_ptr[total];
414
415     last_i = num_i-1;
416     count = 0;
417     prefix = 0;
418     while (last_i >= 0)
419     {
420         struct idx *idx;
421         uint32_t new_prefix;
422         if (count % 102424 == 0 && istty2)
423             fprintf(stderr, "midx: writing %.2f%% (%d/%d)\r",
424                     count*100.0/total, count, total);
425         idx = idxs[last_i];
426         new_prefix = _extract_bits((unsigned char *)idx->cur, bits);
427         while (prefix < new_prefix)
428             table_ptr[prefix++] = htonl(count);
429         memcpy(sha_ptr++, idx->cur, sizeof(struct sha));
430         *name_ptr++ = htonl(_get_idx_i(idx));
431         ++idx->cur;
432         if (idx->cur_name != NULL)
433             ++idx->cur_name;
434         _fix_idx_order(idxs, &last_i);
435         ++count;
436     }
437     while (prefix < (1<<bits))
438         table_ptr[prefix++] = htonl(count);
439     assert(count == total);
440     assert(prefix == (1<<bits));
441     assert(sha_ptr == sha_start+count);
442     assert(name_ptr == name_start+count);
443
444     PyMem_Free(idxs);
445     return PyLong_FromUnsignedLong(count);
446 }
447
448 // This function should technically be macro'd out if it's going to be used
449 // more than ocasionally.  As of this writing, it'll actually never be called
450 // in real world bup scenarios (because our packs are < MAX_INT bytes).
451 static uint64_t htonll(uint64_t value)
452 {
453     static const int endian_test = 42;
454
455     if (*(char *)&endian_test == endian_test) // LSB-MSB
456         return ((uint64_t)htonl(value & 0xFFFFFFFF) << 32) | htonl(value >> 32);
457     return value; // already in network byte order MSB-LSB
458 }
459
460 #define PACK_IDX_V2_HEADERLEN 8
461 #define FAN_ENTRIES 256
462
463 static PyObject *write_idx(PyObject *self, PyObject *args)
464 {
465     PyObject *pf = NULL, *idx = NULL;
466     PyObject *part;
467     FILE *f;
468     unsigned char *fmap = NULL;
469     int flen = 0;
470     uint32_t total = 0;
471     uint32_t count;
472     int i, j, ofs64_count;
473     uint32_t *fan_ptr, *crc_ptr, *ofs_ptr;
474     struct sha *sha_ptr;
475
476     if (!PyArg_ParseTuple(args, "Ow#OI", &pf, &fmap, &flen, &idx, &total))
477         return NULL;
478
479     fan_ptr = (uint32_t *)&fmap[PACK_IDX_V2_HEADERLEN];
480     sha_ptr = (struct sha *)&fan_ptr[FAN_ENTRIES];
481     crc_ptr = (uint32_t *)&sha_ptr[total];
482     ofs_ptr = (uint32_t *)&crc_ptr[total];
483     f = PyFile_AsFile(pf);
484
485     count = 0;
486     ofs64_count = 0;
487     for (i = 0; i < FAN_ENTRIES; ++i)
488     {
489         int plen;
490         part = PyList_GET_ITEM(idx, i);
491         PyList_Sort(part);
492         plen = PyList_GET_SIZE(part);
493         count += plen;
494         *fan_ptr++ = htonl(count);
495         for (j = 0; j < plen; ++j)
496         {
497             unsigned char *sha = NULL;
498             int sha_len = 0;
499             uint32_t crc = 0;
500             uint64_t ofs = 0;
501             if (!PyArg_ParseTuple(PyList_GET_ITEM(part, j), "t#IK",
502                                   &sha, &sha_len, &crc, &ofs))
503                 return NULL;
504             if (sha_len != sizeof(struct sha))
505                 return NULL;
506             memcpy(sha_ptr++, sha, sizeof(struct sha));
507             *crc_ptr++ = htonl(crc);
508             if (ofs > 0x7fffffff)
509             {
510                 uint64_t nofs = htonll(ofs);
511                 if (fwrite(&nofs, sizeof(uint64_t), 1, f) != 1)
512                     return PyErr_SetFromErrno(PyExc_OSError);
513                 ofs = 0x80000000 | ofs64_count++;
514             }
515             *ofs_ptr++ = htonl((uint32_t)ofs);
516         }
517     }
518     return PyLong_FromUnsignedLong(count);
519 }
520
521
522 // I would have made this a lower-level function that just fills in a buffer
523 // with random values, and then written those values from python.  But that's
524 // about 20% slower in my tests, and since we typically generate random
525 // numbers for benchmarking other parts of bup, any slowness in generating
526 // random bytes will make our benchmarks inaccurate.  Plus nobody wants
527 // pseudorandom bytes much except for this anyway.
528 static PyObject *write_random(PyObject *self, PyObject *args)
529 {
530     uint32_t buf[1024/4];
531     int fd = -1, seed = 0, verbose = 0;
532     ssize_t ret;
533     long long len = 0, kbytes = 0, written = 0;
534
535     if (!PyArg_ParseTuple(args, "iLii", &fd, &len, &seed, &verbose))
536         return NULL;
537     
538     srandom(seed);
539     
540     for (kbytes = 0; kbytes < len/1024; kbytes++)
541     {
542         unsigned i;
543         for (i = 0; i < sizeof(buf)/sizeof(buf[0]); i++)
544             buf[i] = random();
545         ret = write(fd, buf, sizeof(buf));
546         if (ret < 0)
547             ret = 0;
548         written += ret;
549         if (ret < (int)sizeof(buf))
550             break;
551         if (verbose && kbytes/1024 > 0 && !(kbytes%1024))
552             fprintf(stderr, "Random: %lld Mbytes\r", kbytes/1024);
553     }
554     
555     // handle non-multiples of 1024
556     if (len % 1024)
557     {
558         unsigned i;
559         for (i = 0; i < sizeof(buf)/sizeof(buf[0]); i++)
560             buf[i] = random();
561         ret = write(fd, buf, len % 1024);
562         if (ret < 0)
563             ret = 0;
564         written += ret;
565     }
566     
567     if (kbytes/1024 > 0)
568         fprintf(stderr, "Random: %lld Mbytes, done.\n", kbytes/1024);
569     return Py_BuildValue("L", written);
570 }
571
572
573 static PyObject *random_sha(PyObject *self, PyObject *args)
574 {
575     static int seeded = 0;
576     uint32_t shabuf[20/4];
577     int i;
578     
579     if (!seeded)
580     {
581         assert(sizeof(shabuf) == 20);
582         srandom(time(NULL));
583         seeded = 1;
584     }
585     
586     if (!PyArg_ParseTuple(args, ""))
587         return NULL;
588     
589     memset(shabuf, 0, sizeof(shabuf));
590     for (i=0; i < 20/4; i++)
591         shabuf[i] = random();
592     return Py_BuildValue("s#", shabuf, 20);
593 }
594
595
596 static PyObject *open_noatime(PyObject *self, PyObject *args)
597 {
598     char *filename = NULL;
599     int attrs, attrs_noatime, fd;
600     if (!PyArg_ParseTuple(args, "s", &filename))
601         return NULL;
602     attrs = O_RDONLY;
603 #ifdef O_NOFOLLOW
604     attrs |= O_NOFOLLOW;
605 #endif
606 #ifdef O_LARGEFILE
607     attrs |= O_LARGEFILE;
608 #endif
609     attrs_noatime = attrs;
610 #ifdef O_NOATIME
611     attrs_noatime |= O_NOATIME;
612 #endif
613     fd = open(filename, attrs_noatime);
614     if (fd < 0 && errno == EPERM)
615     {
616         // older Linux kernels would return EPERM if you used O_NOATIME
617         // and weren't the file's owner.  This pointless restriction was
618         // relaxed eventually, but we have to handle it anyway.
619         // (VERY old kernels didn't recognized O_NOATIME, but they would
620         // just harmlessly ignore it, so this branch won't trigger)
621         fd = open(filename, attrs);
622     }
623     if (fd < 0)
624         return PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename);
625     return Py_BuildValue("i", fd);
626 }
627
628
629 static PyObject *fadvise_done(PyObject *self, PyObject *args)
630 {
631     int fd = -1;
632     long long ofs = 0;
633     if (!PyArg_ParseTuple(args, "iL", &fd, &ofs))
634         return NULL;
635 #ifdef POSIX_FADV_DONTNEED
636     posix_fadvise(fd, 0, ofs, POSIX_FADV_DONTNEED);
637 #endif    
638     return Py_BuildValue("");
639 }
640
641
642 #ifdef FS_IOC_GETFLAGS
643 static PyObject *bup_get_linux_file_attr(PyObject *self, PyObject *args)
644 {
645     int rc;
646     unsigned long attr;
647     char *path;
648     int fd;
649
650     if (!PyArg_ParseTuple(args, "s", &path))
651         return NULL;
652
653     fd = open(path, O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_NOFOLLOW);
654     if (fd == -1)
655         return PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
656
657     attr = 0;
658     rc = ioctl(fd, FS_IOC_GETFLAGS, &attr);
659     if (rc == -1)
660     {
661         close(fd);
662         return PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
663     }
664
665     close(fd);
666     return Py_BuildValue("k", attr);
667 }
668 #endif /* def FS_IOC_GETFLAGS */
669
670
671 #ifdef FS_IOC_SETFLAGS
672 static PyObject *bup_set_linux_file_attr(PyObject *self, PyObject *args)
673 {
674     int rc;
675     unsigned long attr;
676     char *path;
677     int fd;
678
679     if (!PyArg_ParseTuple(args, "sk", &path, &attr))
680         return NULL;
681
682     fd = open(path, O_RDONLY | O_NONBLOCK | O_LARGEFILE | O_NOFOLLOW);
683     if (fd == -1)
684         return PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
685
686     rc = ioctl(fd, FS_IOC_SETFLAGS, &attr);
687     if (rc == -1)
688     {
689         close(fd);
690         return PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
691     }
692
693     close(fd);
694     return Py_BuildValue("O", Py_None);
695 }
696 #endif /* def FS_IOC_SETFLAGS */
697
698
699 #if defined(HAVE_UTIMENSAT) || defined(HAVE_FUTIMES) || defined(HAVE_LUTIMES)
700
701 static int bup_parse_xutime_args(char **path,
702                                  long *access,
703                                  long *access_ns,
704                                  long *modification,
705                                  long *modification_ns,
706                                  PyObject *self, PyObject *args)
707 {
708     if (!PyArg_ParseTuple(args, "s((ll)(ll))",
709                           path,
710                           access, access_ns,
711                           modification, modification_ns))
712         return 0;
713
714     if (isnan(*access))
715     {
716         PyErr_SetString(PyExc_ValueError, "access time is NaN");
717         return 0;
718     }
719     else if (isinf(*access))
720     {
721         PyErr_SetString(PyExc_ValueError, "access time is infinite");
722         return 0;
723     }
724     else if (isnan(*modification))
725     {
726         PyErr_SetString(PyExc_ValueError, "modification time is NaN");
727         return 0;
728     }
729     else if (isinf(*modification))
730     {
731         PyErr_SetString(PyExc_ValueError, "modification time is infinite");
732         return 0;
733     }
734
735     if (isnan(*access_ns))
736     {
737         PyErr_SetString(PyExc_ValueError, "access time ns is NaN");
738         return 0;
739     }
740     else if (isinf(*access_ns))
741     {
742         PyErr_SetString(PyExc_ValueError, "access time ns is infinite");
743         return 0;
744     }
745     else if (isnan(*modification_ns))
746     {
747         PyErr_SetString(PyExc_ValueError, "modification time ns is NaN");
748         return 0;
749     }
750     else if (isinf(*modification_ns))
751     {
752         PyErr_SetString(PyExc_ValueError, "modification time ns is infinite");
753         return 0;
754     }
755
756     return 1;
757 }
758
759 #endif /* defined(HAVE_UTIMENSAT) || defined(HAVE_FUTIMES)
760           || defined(HAVE_LUTIMES) */
761
762
763 #ifdef HAVE_UTIMENSAT
764
765 static PyObject *bup_xutime_ns(PyObject *self, PyObject *args,
766                                int follow_symlinks)
767 {
768     int rc;
769     char *path;
770     long access, access_ns, modification, modification_ns;
771     struct timespec ts[2];
772
773     if (!bup_parse_xutime_args(&path, &access, &access_ns,
774                                &modification, &modification_ns,
775                                self, args))
776        return NULL;
777
778     ts[0].tv_sec = access;
779     ts[0].tv_nsec = access_ns;
780     ts[1].tv_sec = modification;
781     ts[1].tv_nsec = modification_ns;
782     rc = utimensat(AT_FDCWD, path, ts,
783                    follow_symlinks ? 0 : AT_SYMLINK_NOFOLLOW);
784     if (rc != 0)
785         return PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
786
787     return Py_BuildValue("O", Py_None);
788 }
789
790
791 #define BUP_HAVE_BUP_UTIME_NS 1
792 static PyObject *bup_utime_ns(PyObject *self, PyObject *args)
793 {
794     return bup_xutime_ns(self, args, 1);
795 }
796
797
798 #define BUP_HAVE_BUP_LUTIME_NS 1
799 static PyObject *bup_lutime_ns(PyObject *self, PyObject *args)
800 {
801     return bup_xutime_ns(self, args, 0);
802 }
803
804
805 #else /* not defined(HAVE_UTIMENSAT) */
806
807
808 #ifdef HAVE_UTIMES
809 #define BUP_HAVE_BUP_UTIME_NS 1
810 static PyObject *bup_utime_ns(PyObject *self, PyObject *args)
811 {
812     int rc;
813     char *path;
814     long access, access_ns, modification, modification_ns;
815     struct timeval tv[2];
816
817     if (!bup_parse_xutime_args(&path, &access, &access_ns,
818                                &modification, &modification_ns,
819                                self, args))
820        return NULL;
821
822     tv[0].tv_sec = access;
823     tv[0].tv_usec = access_ns / 1000;
824     tv[1].tv_sec = modification;
825     tv[1].tv_usec = modification_ns / 1000;
826     rc = utimes(path, tv);
827     if (rc != 0)
828         return PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
829
830     return Py_BuildValue("O", Py_None);
831 }
832 #endif /* def HAVE_UTIMES */
833
834
835 #ifdef HAVE_LUTIMES
836 #define BUP_HAVE_BUP_LUTIME_NS 1
837 static PyObject *bup_lutime_ns(PyObject *self, PyObject *args)
838 {
839     int rc;
840     char *path;
841     long access, access_ns, modification, modification_ns;
842     struct timeval tv[2];
843
844     if (!bup_parse_xutime_args(&path, &access, &access_ns,
845                                &modification, &modification_ns,
846                                self, args))
847        return NULL;
848
849     tv[0].tv_sec = access;
850     tv[0].tv_usec = access_ns / 1000;
851     tv[1].tv_sec = modification;
852     tv[1].tv_usec = modification_ns / 1000;
853     rc = lutimes(path, tv);
854     if (rc != 0)
855         return PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
856
857     return Py_BuildValue("O", Py_None);
858 }
859 #endif /* def HAVE_LUTIMES */
860
861
862 #endif /* not defined(HAVE_UTIMENSAT) */
863
864
865 #ifdef HAVE_STAT_ST_ATIM
866 # define BUP_STAT_ATIME_NS(st) (st)->st_atim.tv_nsec
867 # define BUP_STAT_MTIME_NS(st) (st)->st_mtim.tv_nsec
868 # define BUP_STAT_CTIME_NS(st) (st)->st_ctim.tv_nsec
869 #elif defined HAVE_STAT_ST_ATIMENSEC
870 # define BUP_STAT_ATIME_NS(st) (st)->st_atimespec.tv_nsec
871 # define BUP_STAT_MTIME_NS(st) (st)->st_mtimespec.tv_nsec
872 # define BUP_STAT_CTIME_NS(st) (st)->st_ctimespec.tv_nsec
873 #else
874 # define BUP_STAT_ATIME_NS(st) 0
875 # define BUP_STAT_MTIME_NS(st) 0
876 # define BUP_STAT_CTIME_NS(st) 0
877 #endif
878
879
880 static PyObject *stat_struct_to_py(const struct stat *st)
881 {
882     long atime_ns = BUP_STAT_ATIME_NS(st);
883     long mtime_ns = BUP_STAT_MTIME_NS(st);
884     long ctime_ns = BUP_STAT_CTIME_NS(st);
885
886     /* Enforce the current timespec nanosecond range expectations. */
887     if (atime_ns < 0 || atime_ns > 999999999)
888     {
889         PyErr_SetString(PyExc_ValueError, "invalid atime timespec nanoseconds");
890         return NULL;
891     }
892     if (mtime_ns < 0 || mtime_ns > 999999999)
893     {
894         PyErr_SetString(PyExc_ValueError, "invalid mtime timespec nanoseconds");
895         return NULL;
896     }
897     if (ctime_ns < 0 || ctime_ns > 999999999)
898     {
899         PyErr_SetString(PyExc_ValueError, "invalid ctime timespec nanoseconds");
900         return NULL;
901     }
902
903     return Py_BuildValue("kkkkkkkk(Ll)(Ll)(Ll)",
904                          (unsigned long) st->st_mode,
905                          (unsigned long) st->st_ino,
906                          (unsigned long) st->st_dev,
907                          (unsigned long) st->st_nlink,
908                          (unsigned long) st->st_uid,
909                          (unsigned long) st->st_gid,
910                          (unsigned long) st->st_rdev,
911                          (unsigned long) st->st_size,
912                          (long long) st->st_atime,
913                          (long) atime_ns,
914                          (long long) st->st_mtime,
915                          (long) mtime_ns,
916                          (long long) st->st_ctime,
917                          (long) ctime_ns);
918 }
919
920
921 static PyObject *bup_stat(PyObject *self, PyObject *args)
922 {
923     int rc;
924     char *filename;
925
926     if (!PyArg_ParseTuple(args, "s", &filename))
927         return NULL;
928
929     struct stat st;
930     rc = stat(filename, &st);
931     if (rc != 0)
932         return PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename);
933     return stat_struct_to_py(&st);
934 }
935
936
937 static PyObject *bup_lstat(PyObject *self, PyObject *args)
938 {
939     int rc;
940     char *filename;
941
942     if (!PyArg_ParseTuple(args, "s", &filename))
943         return NULL;
944
945     struct stat st;
946     rc = lstat(filename, &st);
947     if (rc != 0)
948         return PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename);
949     return stat_struct_to_py(&st);
950 }
951
952
953 static PyObject *bup_fstat(PyObject *self, PyObject *args)
954 {
955     int rc, fd;
956
957     if (!PyArg_ParseTuple(args, "i", &fd))
958         return NULL;
959
960     struct stat st;
961     rc = fstat(fd, &st);
962     if (rc != 0)
963         return PyErr_SetFromErrno(PyExc_OSError);
964     return stat_struct_to_py(&st);
965 }
966
967
968 static PyMethodDef helper_methods[] = {
969     { "selftest", selftest, METH_VARARGS,
970         "Check that the rolling checksum rolls correctly (for unit tests)." },
971     { "blobbits", blobbits, METH_VARARGS,
972         "Return the number of bits in the rolling checksum." },
973     { "splitbuf", splitbuf, METH_VARARGS,
974         "Split a list of strings based on a rolling checksum." },
975     { "bitmatch", bitmatch, METH_VARARGS,
976         "Count the number of matching prefix bits between two strings." },
977     { "firstword", firstword, METH_VARARGS,
978         "Return an int corresponding to the first 32 bits of buf." },
979     { "bloom_contains", bloom_contains, METH_VARARGS,
980         "Check if a bloom filter of 2^nbits bytes contains an object" },
981     { "bloom_add", bloom_add, METH_VARARGS,
982         "Add an object to a bloom filter of 2^nbits bytes" },
983     { "extract_bits", extract_bits, METH_VARARGS,
984         "Take the first 'nbits' bits from 'buf' and return them as an int." },
985     { "merge_into", merge_into, METH_VARARGS,
986         "Merges a bunch of idx and midx files into a single midx." },
987     { "write_idx", write_idx, METH_VARARGS,
988         "Write a PackIdxV2 file from an idx list of lists of tuples" },
989     { "write_random", write_random, METH_VARARGS,
990         "Write random bytes to the given file descriptor" },
991     { "random_sha", random_sha, METH_VARARGS,
992         "Return a random 20-byte string" },
993     { "open_noatime", open_noatime, METH_VARARGS,
994         "open() the given filename for read with O_NOATIME if possible" },
995     { "fadvise_done", fadvise_done, METH_VARARGS,
996         "Inform the kernel that we're finished with earlier parts of a file" },
997 #ifdef FS_IOC_GETFLAGS
998     { "get_linux_file_attr", bup_get_linux_file_attr, METH_VARARGS,
999       "Return the Linux attributes for the given file." },
1000 #endif
1001 #ifdef FS_IOC_SETFLAGS
1002     { "set_linux_file_attr", bup_set_linux_file_attr, METH_VARARGS,
1003       "Set the Linux attributes for the given file." },
1004 #endif
1005 #ifdef BUP_HAVE_BUP_UTIME_NS
1006     { "bup_utime_ns", bup_utime_ns, METH_VARARGS,
1007       "Change path timestamps with up to nanosecond precision." },
1008 #endif
1009 #ifdef BUP_HAVE_BUP_LUTIME_NS
1010     { "bup_lutime_ns", bup_lutime_ns, METH_VARARGS,
1011       "Change path timestamps with up to nanosecond precision;"
1012       " don't follow symlinks." },
1013 #endif
1014     { "stat", bup_stat, METH_VARARGS,
1015       "Extended version of stat." },
1016     { "lstat", bup_lstat, METH_VARARGS,
1017       "Extended version of lstat." },
1018     { "fstat", bup_fstat, METH_VARARGS,
1019       "Extended version of fstat." },
1020     { NULL, NULL, 0, NULL },  // sentinel
1021 };
1022
1023
1024 PyMODINIT_FUNC init_helpers(void)
1025 {
1026     char *e;
1027     PyObject *m = Py_InitModule("_helpers", helper_methods);
1028     if (m == NULL)
1029         return;
1030     e = getenv("BUP_FORCE_TTY");
1031     istty2 = isatty(2) || (atoi(e ? e : "0") & 2);
1032     unpythonize_argv();
1033 }