if (status.si_code == CLD_EXITED) {
if (status.si_status != 0) {
log_warning("%s failed with error code %i.", name, status.si_status);
- return -EPROTO;
+ return status.si_status;
}
log_debug("%s succeeded.", name);
return 0;
}
-/* Returns a short identifier for the various VM/container implementations */
-int detect_virtualization(const char **id) {
- int r;
+int detect_container(const char **id) {
+ FILE *f;
- /* Unfortunately most of these operations require root access
+ /* Unfortunately many of these operations require root access
* in one way or another */
+
if (geteuid() != 0)
return -EPERM;
- if ((r = running_in_chroot()) > 0) {
+ if (running_in_chroot() > 0) {
+
if (id)
*id = "chroot";
- return r;
+ return 1;
}
/* /proc/vz exists in container and outside of the container,
return 1;
}
- return detect_vm(id);
+ if ((f = fopen("/proc/self/cgroup", "r"))) {
+
+ for (;;) {
+ char line[LINE_MAX], *p;
+
+ if (!fgets(line, sizeof(line), f))
+ break;
+
+ if (!(p = strchr(strstrip(line), ':')))
+ continue;
+
+ if (strncmp(p, ":ns:", 4))
+ continue;
+
+ if (!streq(p, ":ns:/")) {
+ fclose(f);
+
+ if (id)
+ *id = "ns";
+
+ return 1;
+ }
+ }
+
+ fclose(f);
+ }
+
+ return 0;
+}
+
+/* Returns a short identifier for the various VM/container implementations */
+int detect_virtualization(const char **id) {
+ static __thread const char *cached_id = NULL;
+ const char *_id;
+ int r;
+
+ if (cached_id) {
+
+ if (cached_id == (const char*) -1)
+ return 0;
+
+ if (id)
+ *id = cached_id;
+
+ return 1;
+ }
+
+ if ((r = detect_container(&_id)) != 0)
+ goto finish;
+
+ r = detect_vm(&_id);
+
+finish:
+ if (r > 0) {
+ cached_id = _id;
+
+ if (id)
+ *id = _id;
+ } else if (r == 0)
+ cached_id = (const char*) -1;
+
+ return r;
}
void execute_directory(const char *directory, DIR *d, char *argv[]) {