X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fshared%2Futil.c;h=67ec5ae747777d7121bb7a9626ea85fd471bf8d9;hb=4f5d327a49e1a40ae0a3b8f1855dc90f3c0d953f;hp=0234f3b483de6acd8f38e96553d455dcd02a0eb4;hpb=344de60901f0e3ce0d2f112b7be97fc6d0e2f071;p=elogind.git diff --git a/src/shared/util.c b/src/shared/util.c index 0234f3b48..67ec5ae74 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -50,7 +50,6 @@ #include #include #include -#include #include #include #include @@ -2707,7 +2706,7 @@ int parse_usec(const char *t, usec_t *usec) { { "m", USEC_PER_MINUTE }, { "usec", 1ULL }, { "us", 1ULL }, - { "", USEC_PER_SEC }, + { "", USEC_PER_SEC }, /* default is sec */ }; const char *p; @@ -2753,6 +2752,71 @@ int parse_usec(const char *t, usec_t *usec) { return 0; } +int parse_nsec(const char *t, nsec_t *nsec) { + static const struct { + const char *suffix; + nsec_t nsec; + } table[] = { + { "sec", NSEC_PER_SEC }, + { "s", NSEC_PER_SEC }, + { "min", NSEC_PER_MINUTE }, + { "hr", NSEC_PER_HOUR }, + { "h", NSEC_PER_HOUR }, + { "d", NSEC_PER_DAY }, + { "w", NSEC_PER_WEEK }, + { "msec", NSEC_PER_MSEC }, + { "ms", NSEC_PER_MSEC }, + { "m", NSEC_PER_MINUTE }, + { "usec", NSEC_PER_USEC }, + { "us", NSEC_PER_USEC }, + { "nsec", 1ULL }, + { "ns", 1ULL }, + { "", 1ULL }, /* default is nsec */ + }; + + const char *p; + nsec_t r = 0; + + assert(t); + assert(nsec); + + p = t; + do { + long long l; + char *e; + unsigned i; + + errno = 0; + l = strtoll(p, &e, 10); + + if (errno != 0) + return -errno; + + if (l < 0) + return -ERANGE; + + if (e == p) + return -EINVAL; + + e += strspn(e, WHITESPACE); + + for (i = 0; i < ELEMENTSOF(table); i++) + if (startswith(e, table[i].suffix)) { + r += (nsec_t) l * table[i].nsec; + p = e + strlen(table[i].suffix); + break; + } + + if (i >= ELEMENTSOF(table)) + return -EINVAL; + + } while (*p != 0); + + *nsec = r; + + return 0; +} + int parse_bytes(const char *t, off_t *bytes) { static const struct { const char *suffix; @@ -3139,14 +3203,14 @@ int get_ctty(pid_t pid, dev_t *_devnr, char **r) { return 0; } -static int rm_rf_children(int fd, bool only_dirs, bool honour_sticky) { +int rm_rf_children(int fd, bool only_dirs, bool honour_sticky, struct stat *root_dev) { DIR *d; int ret = 0; assert(fd >= 0); /* This returns the first error we run into, but nevertheless - * tries to go on */ + * tries to go on. This closes the passed fd. */ d = fdopendir(fd); if (!d) { @@ -3157,7 +3221,8 @@ static int rm_rf_children(int fd, bool only_dirs, bool honour_sticky) { for (;;) { struct dirent buf, *de; - bool is_dir, keep_around = false; + bool is_dir, keep_around; + struct stat st; int r; r = readdir_r(d, &buf, &de); @@ -3172,51 +3237,41 @@ static int rm_rf_children(int fd, bool only_dirs, bool honour_sticky) { if (streq(de->d_name, ".") || streq(de->d_name, "..")) continue; - if (de->d_type == DT_UNKNOWN) { - struct stat st; - + if (de->d_type == DT_UNKNOWN || + honour_sticky || + (de->d_type == DT_DIR && root_dev)) { if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { if (ret == 0 && errno != ENOENT) ret = -errno; continue; } - if (honour_sticky) - keep_around = - (st.st_uid == 0 || st.st_uid == getuid()) && - (st.st_mode & S_ISVTX); - is_dir = S_ISDIR(st.st_mode); - + keep_around = + honour_sticky && + (st.st_uid == 0 || st.st_uid == getuid()) && + (st.st_mode & S_ISVTX); } else { - if (honour_sticky) { - struct stat st; - - if (fstatat(fd, de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) { - if (ret == 0 && errno != ENOENT) - ret = -errno; - continue; - } - - keep_around = - (st.st_uid == 0 || st.st_uid == getuid()) && - (st.st_mode & S_ISVTX); - } - is_dir = de->d_type == DT_DIR; + keep_around = false; } if (is_dir) { int subdir_fd; - subdir_fd = openat(fd, de->d_name, O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); + /* if root_dev is set, remove subdirectories only, if device is same as dir */ + if (root_dev && st.st_dev != root_dev->st_dev) + continue; + + subdir_fd = openat(fd, de->d_name, + O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC|O_NOFOLLOW|O_NOATIME); if (subdir_fd < 0) { if (ret == 0 && errno != ENOENT) ret = -errno; continue; } - r = rm_rf_children(subdir_fd, only_dirs, honour_sticky); + r = rm_rf_children(subdir_fd, only_dirs, honour_sticky, root_dev); if (r < 0 && ret == 0) ret = r; @@ -3259,7 +3314,7 @@ int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky return 0; } - r = rm_rf_children(fd, only_dirs, honour_sticky); + r = rm_rf_children(fd, only_dirs, honour_sticky, NULL); if (delete_root) { @@ -5639,3 +5694,34 @@ bool is_valid_documentation_url(const char *url) { return false; } + +bool in_initrd(void) { + static int saved = -1; + + if (saved < 0) + saved = access("/etc/initrd-release", F_OK) >= 0; + + return saved; +} + +void warn_melody(void) { + int fd; + + fd = open("/dev/console", O_WRONLY|O_CLOEXEC|O_NOCTTY); + if (fd < 0) + return; + + /* Yeah, this is synchronous. Kinda sucks. Bute well... */ + + ioctl(fd, KIOCSOUND, (int)(1193180/440)); + usleep(125*USEC_PER_MSEC); + + ioctl(fd, KIOCSOUND, (int)(1193180/220)); + usleep(125*USEC_PER_MSEC); + + ioctl(fd, KIOCSOUND, (int)(1193180/220)); + usleep(125*USEC_PER_MSEC); + + ioctl(fd, KIOCSOUND, 0); + close_nointr_nofail(fd); +}