tests: fix virpcitest with read-only srcdir

'make distcheck' has been broken since commit 21685c9; basically,
it emulates the case of a read-only $(srcdir) (such as building
from a tarball exploded onto a CD-ROM), but we were creating our
fake pci device as a symlink into $(srcdir) and failing when that
requires opening the config file for writing:

 3) testVirPCIDeviceReset                                             ... libvirt:  error : Failed to open config space file '/sys/bus/pci/devices/0000:00:01.0/config': Permission denied

Fix it by copying rather than symlinking.

* tests/virpcimock.c (make_file): Add parameter to allow binary
creation; adjust all callers.
(pci_device_new_from_stub): Copy rather than symlink.

Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
Eric Blake 2013-11-27 14:59:52 -07:00
parent 0aa873d741
commit e821de2c5a

View File

@ -154,10 +154,13 @@ static int pci_driver_handle_remove_id(const char *path);
static void static void
make_file(const char *path, make_file(const char *path,
const char *name, const char *name,
const char *value) const char *value,
ssize_t len)
{ {
int fd = -1; int fd = -1;
char *filepath = NULL; char *filepath = NULL;
if (value && len == -1)
len = strlen(value);
if (virAsprintfQuiet(&filepath, "%s/%s", path, name) < 0) if (virAsprintfQuiet(&filepath, "%s/%s", path, name) < 0)
ABORT_OOM(); ABORT_OOM();
@ -165,7 +168,7 @@ make_file(const char *path,
if ((fd = realopen(filepath, O_CREAT|O_WRONLY, 0666)) < 0) if ((fd = realopen(filepath, O_CREAT|O_WRONLY, 0666)) < 0)
ABORT("Unable to open: %s", filepath); ABORT("Unable to open: %s", filepath);
if (value && safewrite(fd, value, strlen(value)) != strlen(value)) if (value && safewrite(fd, value, len) != len)
ABORT("Unable to write: %s", filepath); ABORT("Unable to write: %s", filepath);
VIR_FORCE_CLOSE(fd); VIR_FORCE_CLOSE(fd);
@ -302,7 +305,7 @@ pci_device_new_from_stub(const struct pciDevice *data)
{ {
struct pciDevice *dev; struct pciDevice *dev;
char *devpath; char *devpath;
char *configSrc, *configDst; char *configSrc;
char tmp[32]; char tmp[32];
struct stat sb; struct stat sb;
@ -321,25 +324,32 @@ pci_device_new_from_stub(const struct pciDevice *data)
* symlink it. Otherwise create a dummy config file. */ * symlink it. Otherwise create a dummy config file. */
if ((realstat && realstat(configSrc, &sb) == 0) || if ((realstat && realstat(configSrc, &sb) == 0) ||
(real__xstat && real__xstat(_STAT_VER, configSrc, &sb) == 0)) { (real__xstat && real__xstat(_STAT_VER, configSrc, &sb) == 0)) {
/* On success make symlink to @configSrc */ /* On success, copy @configSrc into the destination (a copy,
if (virAsprintfQuiet(&configDst, "%s/config", devpath) < 0) * rather than a symlink, is required since we write into the
ABORT_OOM(); * file, and parallel VPATH builds must not stomp on the
* original; besides, 'make distcheck' requires the original
* to be read-only */
char *buf;
ssize_t len;
if (symlink(configSrc, configDst) < 0) if ((len = virFileReadAll(configSrc, 4096, &buf)) < 0)
ABORT("Unable to create symlink: %s", configDst); ABORT("Unable to read config file '%s'", configSrc);
make_file(devpath, "config", buf, len);
VIR_FREE(buf);
} else { } else {
/* If there's no config data in the virpcitestdata dir, create a dummy /* If there's no config data in the virpcitestdata dir, create a dummy
* config file */ * config file */
make_file(devpath, "config", "some dummy config"); make_file(devpath, "config", "some dummy config", -1);
} }
if (snprintf(tmp, sizeof(tmp), "0x%.4x", dev->vendor) < 0) if (snprintf(tmp, sizeof(tmp), "0x%.4x", dev->vendor) < 0)
ABORT("@tmp overflow"); ABORT("@tmp overflow");
make_file(devpath, "vendor", tmp); make_file(devpath, "vendor", tmp, -1);
if (snprintf(tmp, sizeof(tmp), "0x%.4x", dev->device) < 0) if (snprintf(tmp, sizeof(tmp), "0x%.4x", dev->device) < 0)
ABORT("@tmp overflow"); ABORT("@tmp overflow");
make_file(devpath, "device", tmp); make_file(devpath, "device", tmp, -1);
if (pci_device_autobind(dev) < 0) if (pci_device_autobind(dev) < 0)
ABORT("Unable to bind: %s", data->id); ABORT("Unable to bind: %s", data->id);
@ -348,6 +358,7 @@ pci_device_new_from_stub(const struct pciDevice *data)
ABORT_OOM(); ABORT_OOM();
VIR_FREE(devpath); VIR_FREE(devpath);
VIR_FREE(configSrc);
} }
static struct pciDevice * static struct pciDevice *
@ -425,10 +436,10 @@ pci_driver_new(const char *name, ...)
va_end(args); va_end(args);
make_file(driverpath, "bind", NULL); make_file(driverpath, "bind", NULL, -1);
make_file(driverpath, "unbind", NULL); make_file(driverpath, "unbind", NULL, -1);
make_file(driverpath, "new_id", NULL); make_file(driverpath, "new_id", NULL, -1);
make_file(driverpath, "remove_id", NULL); make_file(driverpath, "remove_id", NULL, -1);
if (VIR_APPEND_ELEMENT_QUIET(pciDrivers, nPciDrivers, driver) < 0) if (VIR_APPEND_ELEMENT_QUIET(pciDrivers, nPciDrivers, driver) < 0)
ABORT_OOM(); ABORT_OOM();