X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Futil.c;h=88fd78ec8d61f5b0de698d085e9e68c2ec83b346;hb=11689d2a021d95a8447d938180e0962cd9439763;hp=bda3c93ae38d91ddb54e74bb44131dcab269c5c8;hpb=abe4aa144beb3a68e9f2c98a4563e0a99f28c7a1;p=elogind.git diff --git a/src/shared/util.c b/src/shared/util.c index bda3c93ae..88fd78ec8 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -62,6 +62,7 @@ #include #include #include +#include #undef basename #ifdef HAVE_SYS_AUXV_H @@ -4005,7 +4006,7 @@ bool tty_is_vc_resolve(const char *tty) { const char *default_term_for_tty(const char *tty) { assert(tty); - return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt102"; + return tty_is_vc_resolve(tty) ? "TERM=linux" : "TERM=vt220"; } bool dirent_is_file(const struct dirent *de) { @@ -6980,10 +6981,10 @@ int bind_remount_recursive(const char *prefix, bool ro) { if (mount(cleaned, cleaned, NULL, MS_BIND|MS_REC, NULL) < 0) return -errno; - r = get_mount_flags(prefix, &orig_flags); - if (r < 0) - return r; + orig_flags = 0; + (void) get_mount_flags(cleaned, &orig_flags); orig_flags &= ~MS_RDONLY; + if (mount(NULL, prefix, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) return -errno; @@ -7004,10 +7005,13 @@ int bind_remount_recursive(const char *prefix, bool ro) { if (r < 0) return r; - r = get_mount_flags(x, &orig_flags); - if (r < 0) - return r; + /* Try to reuse the original flag set, but + * don't care for errors, in case of + * obstructed mounts */ + orig_flags = 0; + (void) get_mount_flags(x, &orig_flags); orig_flags &= ~MS_RDONLY; + if (mount(NULL, x, NULL, orig_flags|MS_BIND|MS_REMOUNT|(ro ? MS_RDONLY : 0), NULL) < 0) { /* Deal with mount points that are @@ -7672,3 +7676,100 @@ int fd_setcrtime(int fd, usec_t usec) { return 0; } + +int same_fd(int a, int b) { + struct stat sta, stb; + pid_t pid; + int r, fa, fb; + + assert(a >= 0); + assert(b >= 0); + + /* Compares two file descriptors. Note that semantics are + * quite different depending on whether we have kcmp() or we + * don't. If we have kcmp() this will only return true for + * dup()ed file descriptors, but not otherwise. If we don't + * have kcmp() this will also return true for two fds of the same + * file, created by separate open() calls. Since we use this + * call mostly for filtering out duplicates in the fd store + * this difference hopefully doesn't matter too much. */ + + if (a == b) + return true; + + /* Try to use kcmp() if we have it. */ + pid = getpid(); + r = kcmp(pid, pid, KCMP_FILE, a, b); + if (r == 0) + return true; + if (r > 0) + return false; + if (errno != ENOSYS) + return -errno; + + /* We don't have kcmp(), use fstat() instead. */ + if (fstat(a, &sta) < 0) + return -errno; + + if (fstat(b, &stb) < 0) + return -errno; + + if ((sta.st_mode & S_IFMT) != (stb.st_mode & S_IFMT)) + return false; + + /* We consider all device fds different, since two device fds + * might refer to quite different device contexts even though + * they share the same inode and backing dev_t. */ + + if (S_ISCHR(sta.st_mode) || S_ISBLK(sta.st_mode)) + return false; + + if (sta.st_dev != stb.st_dev || sta.st_ino != stb.st_ino) + return false; + + /* The fds refer to the same inode on disk, let's also check + * if they have the same fd flags. This is useful to + * distuingish the read and write side of a pipe created with + * pipe(). */ + fa = fcntl(a, F_GETFL); + if (fa < 0) + return -errno; + + fb = fcntl(b, F_GETFL); + if (fb < 0) + return -errno; + + return fa == fb; +} + +int chattr_fd(int fd, bool b, int mask) { + int old_attr, new_attr; + + assert(fd >= 0); + + if (ioctl(fd, FS_IOC_GETFLAGS, &old_attr) < 0) + return -errno; + + if (b) + new_attr = old_attr | mask; + else + new_attr = old_attr & ~mask; + + if (new_attr == old_attr) + return 0; + + if (ioctl(fd, FS_IOC_SETFLAGS, &new_attr) < 0) + return -errno; + + return 0; +} + +int chattr_path(const char *p, bool b, int mask) { + _cleanup_close_ int fd = -1; + + fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fd < 0) + return -errno; + + return chattr_fd(fd, b, mask); +}