#define BUP_HAVE_FILE_ATTRS 1
#endif
+/*
+ * Check for incomplete UTIMENSAT support (NetBSD 6), and if so,
+ * pretend we don't have it.
+ */
+#if !defined(AT_FDCWD) || !defined(AT_SYMLINK_NOFOLLOW)
+#undef HAVE_UTIMENSAT
+#endif
+
#ifndef FS_NOCOW_FL
// Of course, this assumes it's a bitfield value.
#define FS_NOCOW_FL 0
static int istty2 = 0;
+
+#ifndef htonll
+// This function should technically be macro'd out if it's going to be used
+// more than ocasionally. As of this writing, it'll actually never be called
+// in real world bup scenarios (because our packs are < MAX_INT bytes).
+static uint64_t htonll(uint64_t value)
+{
+ static const int endian_test = 42;
+
+ if (*(char *)&endian_test == endian_test) // LSB-MSB
+ return ((uint64_t)htonl(value & 0xFFFFFFFF) << 32) | htonl(value >> 32);
+ return value; // already in network byte order MSB-LSB
+}
+#endif
+
+
// At the moment any code that calls INTGER_TO_PY() will have to
// disable -Wtautological-compare for clang. See below.
return PyLong_FromUnsignedLong(count);
}
-// This function should technically be macro'd out if it's going to be used
-// more than ocasionally. As of this writing, it'll actually never be called
-// in real world bup scenarios (because our packs are < MAX_INT bytes).
-static uint64_t htonll(uint64_t value)
-{
- static const int endian_test = 42;
-
- if (*(char *)&endian_test == endian_test) // LSB-MSB
- return ((uint64_t)htonl(value & 0xFFFFFFFF) << 32) | htonl(value >> 32);
- return value; // already in network byte order MSB-LSB
-}
-
#define FAN_ENTRIES 256
static PyObject *write_idx(PyObject *self, PyObject *args)
}
+// Currently the Linux kernel and FUSE disagree over the type for
+// FS_IOC_GETFLAGS and FS_IOC_SETFLAGS. The kernel actually uses int,
+// but FUSE chose long (matching the declaration in linux/fs.h). So
+// if you use int, and then traverse a FUSE filesystem, you may
+// corrupt the stack. But if you use long, then you may get invalid
+// results on big-endian systems.
+//
+// For now, we just use long, and then disable Linux attrs entirely
+// (with a warning) in helpers.py on systems that are affected.
+
#ifdef BUP_HAVE_FILE_ATTRS
static PyObject *bup_get_linux_file_attr(PyObject *self, PyObject *args)
{
int rc;
- unsigned int attr;
+ unsigned long attr;
char *path;
int fd;
if (fd == -1)
return PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
- attr = 0;
+ attr = 0; // Handle int/long mismatch (see above)
rc = ioctl(fd, FS_IOC_GETFLAGS, &attr);
if (rc == -1)
{
close(fd);
return PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
}
-
close(fd);
- return Py_BuildValue("I", attr);
+ assert(attr <= UINT_MAX); // Kernel type is actually int
+ return PyLong_FromUnsignedLong(attr);
}
#endif /* def BUP_HAVE_FILE_ATTRS */
static PyObject *bup_set_linux_file_attr(PyObject *self, PyObject *args)
{
int rc;
- unsigned int orig_attr, attr;
+ unsigned long orig_attr;
+ unsigned int attr;
char *path;
PyObject *py_attr;
int fd;
| FS_TOPDIR_FL | FS_NOCOW_FL;
// The extents flag can't be removed, so don't (see chattr(1) and chattr.c).
+ orig_attr = 0; // Handle int/long mismatch (see above)
rc = ioctl(fd, FS_IOC_GETFLAGS, &orig_attr);
+ assert(orig_attr <= UINT_MAX); // Kernel type is actually int
if (rc == -1)
{
close(fd);
return PyErr_SetFromErrnoWithFilename(PyExc_OSError, path);
}
- attr |= (orig_attr & FS_EXTENT_FL);
+ attr |= ((unsigned int) orig_attr) & FS_EXTENT_FL;
rc = ioctl(fd, FS_IOC_SETFLAGS, &attr);
if (rc == -1)
if (m == NULL)
return;
-#ifdef HAVE_UTIMENSAT
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wtautological-compare" // For INTEGER_TO_PY().
+#ifdef HAVE_UTIMENSAT
{
PyObject *value;
value = INTEGER_TO_PY(AT_FDCWD);
PyObject_SetAttrString(m, "UTIME_NOW", value);
Py_DECREF(value);
}
-#pragma clang diagnostic pop // ignored "-Wtautological-compare"
#endif
+ {
+ PyObject *value;
+ const long arg_max = sysconf(_SC_ARG_MAX);
+ if (arg_max == -1)
+ {
+ fprintf(stderr, "Cannot find SC_ARG_MAX, please report a bug.\n");
+ exit(1);
+ }
+ value = INTEGER_TO_PY(arg_max);
+ PyObject_SetAttrString(m, "SC_ARG_MAX", value);
+ Py_DECREF(value);
+ }
+#pragma clang diagnostic pop // ignored "-Wtautological-compare"
e = getenv("BUP_FORCE_TTY");
istty2 = isatty(2) || (atoi(e ? e : "0") & 2);