From 087b1d251415e76d7910ec6b13232cb61d19be77 Mon Sep 17 00:00:00 2001 From: Otavio Pontes Date: Tue, 3 Mar 2020 14:45:08 -0800 Subject: [PATCH] sys: Prefer to use api from sys than using stat directly --- src/clean.c | 20 +++++++++----------- src/lib/sys.c | 22 ++++++++++++++++++++++ src/lib/sys.h | 13 +++++++++++++ src/staging.c | 15 ++++----------- src/verify.c | 5 ++--- 5 files changed, 50 insertions(+), 25 deletions(-) diff --git a/src/clean.c b/src/clean.c index bdfe44f9..cecbabcf 100644 --- a/src/clean.c +++ b/src/clean.c @@ -30,8 +30,6 @@ #define FLAG_ALL 2000 #define FLAG_DRY_RUN 2001 -static const int BLOCK_SIZE = 512; - static void print_help(void) { print("Remove cached content used for updates from state directory\n\n"); @@ -117,8 +115,7 @@ static enum swupd_code remove_if(const char *path, bool dry_run, remove_predicat { int ret = SWUPD_OK; DIR *dir; - struct stat st; - long size; + long size, hardlink_count; dir = opendir(path); if (!dir) { @@ -153,17 +150,20 @@ static enum swupd_code remove_if(const char *path, bool dry_run, remove_predicat continue; } - if (lstat(file, &st) == 0) { + hardlink_count = sys_file_hardlink_count(file); + if (hardlink_count == 1) { /* a file being removed (unlinked) may have many hardlinks which may * stay in the system, so the only files being trully removed are * those which only have one inode left in the system. * This also means that when doing dry-run we can only guess how * much space we would free since we cannot know what inodes will * have all their hardlinks removed */ - size = st.st_nlink == 1 ? (st.st_blocks * BLOCK_SIZE) : 0; + size = sys_get_file_size(file); } else { size = 0; - warn("Couldn't get file size: %s\n", file); + if (hardlink_count < 0) { + warn("Couldn't get file size: %s\n", file); + } } if (dry_run) { @@ -312,7 +312,6 @@ end: static enum swupd_code clean_staged_manifests(const char *path, bool dry_run, bool all) { DIR *dir; - struct stat st; long size; dir = opendir(path); @@ -370,9 +369,8 @@ static enum swupd_code clean_staged_manifests(const char *path, bool dry_run, bo } /* Remove empty dirs if possible. */ - if (lstat(version_dir, &st) == 0) { - size = st.st_blocks * BLOCK_SIZE; - } else { + size = sys_get_file_size(version_dir); + if (size < 0) { size = 0; } if (!rmdir(version_dir) || (dry_run && all)) { diff --git a/src/lib/sys.c b/src/lib/sys.c index 45f83fab..62f9cca2 100644 --- a/src/lib/sys.c +++ b/src/lib/sys.c @@ -290,6 +290,17 @@ bool sys_file_is_hardlink(const char *file1, const char *file2) return lstat(file1, &sb) == 0 && lstat(file2, &sb2) == 0 && sb.st_ino == sb2.st_ino; } +long sys_file_hardlink_count(const char *file) +{ + struct stat st; + + if (lstat(file, &st)) { + return -errno; + } + + return st.st_nlink; +} + void journal_log_error(const char *message) { if (!message) { @@ -501,3 +512,14 @@ int sys_rm(const char *filename) return sys_rmdir(filename); } + +long sys_get_file_size(const char *filename) +{ + static const int BLOCK_SIZE = 512; + struct stat st; + + if (lstat(filename, &st) == 0) { + return st.st_blocks * BLOCK_SIZE; + } + return -errno; +} diff --git a/src/lib/sys.h b/src/lib/sys.h index f81a3410..44cf1b76 100644 --- a/src/lib/sys.h +++ b/src/lib/sys.h @@ -220,6 +220,19 @@ int sys_rm_recursive(const char *filename); */ int sys_rm(const char *filename); +/** + * @brief Get the count of hard links to a file. + * + * @return Return the hard link count or a negative number on errors. + */ +long sys_file_hardlink_count(const char *file); + +/** + * @brief Get the size of a file. + * + * @return Return the size of a file or a negative number on errors. + */ +long sys_get_file_size(const char *filename); /** * @brief Run a systemctl command with the informed parameters. */ diff --git a/src/staging.c b/src/staging.c index 80c6cd03..a643b30e 100644 --- a/src/staging.c +++ b/src/staging.c @@ -75,8 +75,6 @@ enum swupd_code do_staging(struct file *file, struct manifest *MoM) char *rename_tmpdir = NULL; char real_path[4096] = { 0 }; struct stat s; - struct stat buf; - int err; int ret; tmp = strdup_or_die(file->filename); @@ -95,14 +93,13 @@ enum swupd_code do_staging(struct file *file, struct manifest *MoM) /* make sure the directory where the file should be copied to exists * and is in deed a directory */ string_or_die(&targetpath, "%s%s", globals.path_prefix, rel_dir); - ret = stat(targetpath, &s); - if ((ret == -1) && (errno == ENOENT)) { + if (!sys_filelink_exists(targetpath)) { if (MoM) { verify_fix_path(dir, MoM); } else { debug("Target directory does not exist: %s. Auto-fix disabled\n", targetpath); } - } else if (!S_ISDIR(s.st_mode)) { + } else if (!sys_filelink_is_dir(targetpath)) { error("Target exists but is NOT a directory: %s\n", targetpath); } @@ -242,8 +239,7 @@ enum swupd_code do_staging(struct file *file, struct manifest *MoM) free_and_clear_pointer(&file->staging); string_or_die(&file->staging, "%s%s/.update.%s", globals.path_prefix, rel_dir, base); - err = lstat(file->staging, &buf); - if (err != 0) { + if (!sys_file_exists(file->staging)) { free_and_clear_pointer(&file->staging); ret = SWUPD_COULDNT_CREATE_FILE; goto out; @@ -288,16 +284,13 @@ int rename_staged_file_to_final(struct file *file) } else if (file->is_dir || file->is_ghosted) { ret = 0; } else { - struct stat stat; - ret = lstat(target, &stat); - /* If the file was previously a directory but no longer, then * we need to move it out of the way. * This should not happen because the server side complains * when creating update content that includes such a state * change. But...you never know. */ - if ((ret == 0) && (S_ISDIR(stat.st_mode))) { + if (sys_is_dir(target)) { char *lostnfound; char *base; diff --git a/src/verify.c b/src/verify.c index 09e03263..b7d0cf52 100644 --- a/src/verify.c +++ b/src/verify.c @@ -511,7 +511,6 @@ static void remove_orphaned_files(struct list *files_to_verify, bool repair) struct file *file; char *fullname; char *base; - struct stat sb; int fd; file = iter->data; @@ -534,7 +533,7 @@ static void remove_orphaned_files(struct list *files_to_verify, bool repair) fullname = sys_path_join(globals.path_prefix, file->filename); - if (lstat(fullname, &sb) != 0) { + if (!sys_file_exists(fullname)) { /* correctly, the file is not present */ goto out; } @@ -559,7 +558,7 @@ static void remove_orphaned_files(struct list *files_to_verify, bool repair) base = basename(fullname); - if (!S_ISDIR(sb.st_mode)) { + if (!sys_is_dir(fullname)) { ret = unlinkat(fd, base, 0); if (ret && errno != ENOENT) { warn(" -> Failed to remove %s (%i: %s)\n", fullname, errno, strerror(errno));