X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Futil.c;h=7d753e448a4f5da69b8d86045d90b6388a85a921;hb=3c7560019e623e6e0d03a860b4f19a3a8715feca;hp=f01022ed0b3a6f20ba9ba39919bbce8a19bdb7f9;hpb=a354329f724d6ce913d2ccffb2be8f3327a67faa;p=elogind.git diff --git a/src/shared/util.c b/src/shared/util.c index f01022ed0..7d753e448 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 @@ -7666,6 +7670,9 @@ int fd_setcrtime(int fd, usec_t usec) { assert(fd >= 0); + if (usec <= 0) + usec = now(CLOCK_REALTIME); + le = htole64((uint64_t) usec); if (fsetxattr(fd, "user.crtime_usec", &le, sizeof(le), 0) < 0) return -errno; @@ -7675,13 +7682,35 @@ int fd_setcrtime(int fd, usec_t usec) { 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; @@ -7691,9 +7720,59 @@ int same_fd(int a, int b) { if ((sta.st_mode & S_IFMT) != (stb.st_mode & S_IFMT)) return false; - if (S_ISREG(sta.st_mode) || S_ISDIR(sta.st_mode) || S_ISFIFO(sta.st_mode) || S_ISSOCK(sta.st_mode) || S_ISLNK(sta.st_mode)) - return (sta.st_dev == stb.st_dev) && (sta.st_ino == stb.st_ino); + /* 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. */ - /* We consider all device fds different... */ - return false; + 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); }