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