sys: Prefer to use api from sys than using stat directly

This commit is contained in:
Otavio Pontes
2020-03-04 12:04:05 -08:00
parent 591cc3308b
commit 087b1d2514
5 changed files with 50 additions and 25 deletions
+9 -11
View File
@@ -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)) {
+22
View File
@@ -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;
}
+13
View File
@@ -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.
*/
+4 -11
View File
@@ -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;
+2 -3
View File
@@ -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));