if (ignore_file(de->d_name))
continue;
- if ((r = safe_atoi(de->d_name, &fd)) < 0)
- goto finish;
+ if (safe_atoi(de->d_name, &fd) < 0)
+ /* Let's better ignore this, just in case */
+ continue;
if (fd < 3)
continue;
continue;
}
- if ((r = close_nointr(fd)) < 0) {
+ if (close_nointr(fd) < 0) {
/* Valgrind has its own FD and doesn't want to have it closed */
- if (errno != EBADF)
- goto finish;
+ if (errno != EBADF && r == 0)
+ r = -errno;
}
}
- r = 0;
-
-finish:
closedir(d);
return r;
}
if (streq(s, "tty")) {
free(s);
- return get_ctty(r);
+ return get_ctty(r, NULL);
}
*r = s;
return 0;
}
-int get_ctty(char **r) {
+int get_ctty(char **r, dev_t *_devnr) {
int k;
char fn[128], *s, *b, *p;
dev_t devnr;
if (k != -ENOENT)
return k;
+ /* This is an ugly hack */
+ if (major(devnr) == 136) {
+ if (asprintf(&b, "pts/%lu", (unsigned long) minor(devnr)) < 0)
+ return -ENOMEM;
+
+ *r = b;
+ if (_devnr)
+ *_devnr = devnr;
+
+ return 0;
+ }
+
/* Probably something like the ptys which have no
* symlink in /dev/char. Let's return something
* vaguely useful. */
return -ENOMEM;
*r = b;
+ if (_devnr)
+ *_devnr = devnr;
+
return 0;
}
return -ENOMEM;
*r = b;
+ if (_devnr)
+ *_devnr = devnr;
+
return 0;
}
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);
}
void freeze(void) {
+
+ /* Make sure nobody waits for us on a socket anymore */
+ close_all_fds(NULL, 0);
+
sync();
for (;;)
/* Returns a short identifier for the various VM/container implementations */
int detect_virtualization(const char **id) {
int r;
+ static __thread const char *cached_id = NULL;
+ const char *_id;
+ FILE *f;
+
+ if (cached_id) {
+
+ if (cached_id == (const char*) -1)
+ return 0;
+
+ if (id)
+ *id = cached_id;
+
+ return 1;
+ }
/* Unfortunately most of these operations require root access
* in one way or another */
return -EPERM;
if ((r = running_in_chroot()) > 0) {
- if (id)
- *id = "chroot";
+ _id = "chroot";
+ r = 1;
+ goto finish;
+ }
- return r;
+ 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);
+
+ r = 1;
+ _id = "ns";
+ goto finish;
+ }
+ }
+
+ fclose(f);
}
/* /proc/vz exists in container and outside of the container,
* /proc/bc only outside of the container. */
if (access("/proc/vz", F_OK) >= 0 &&
access("/proc/bc", F_OK) < 0) {
+ _id = "openvz";
+ r = 1;
+ goto finish;
+ }
- if (id)
- *id = "openvz";
+ r = detect_vm(&_id);
- return 1;
- }
+finish:
+ if (r < 0)
+ return r;
+ else if (r > 0)
+ cached_id = _id;
+ else
+ cached_id = (const char*) -1;
+
+ if (id)
+ *id = _id;
- return detect_vm(id);
+ return r;
}
void execute_directory(const char *directory, DIR *d, char *argv[]) {