/* ckutil.c - utility functions for ck ---------------------------------*- C -*- * * This file is part of ck, the config keeper * * ----------------------------------------------------------------------------- * * Copyright (C) 2018 Anastasis Grammenos * GPLv3 (see LICENCE for the full notice) * * -------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include "ckerrlog.h" ERRLOG(utility); int util_is_dir(const char *path) { if (!path) { return 0; } DIR *dir; dir = opendir(path); if (!dir) { return 0; } closedir(dir); return 1; } int util_file_exists(const char* path, char *absPath) { if (!path || !absPath) { return 0; } struct stat st = {0}; if (stat(path, &st) == -1) { return 0; } if (absPath) { realpath(path, absPath); } return 1; } int util_is_file_rw(const char *path) { if (!path) { return 0; } if (access(path, R_OK | W_OK) == 0) { return 1; } return 0; } int util_is_file_link(const char *path) { if (!path) { return 0; } struct stat buf; lstat(path, &buf); if (S_ISLNK(buf.st_mode)) { return 0; } return 1; } void util_mkdir(const char *name) { if (!name) { return; } mkdir(name, 0755); } int util_move_file(const char *path, const char* dest) { if (!path || !dest) { return 0; } int srcFile = open(path, O_RDONLY); int destFile = open(dest, O_WRONLY | O_CREAT); struct stat st, newSt; fstat(srcFile, &st); sendfile(destFile, srcFile, NULL, (size_t)st.st_size); close(srcFile); fchmod(destFile, st.st_mode); fstat(destFile, &newSt); if (st.st_size == newSt.st_size) { unlink(path); close(destFile); return 0; } close(destFile); return -1; } int util_symlink_file(const char *path, const char* dest) { if (!path || !dest) { return -1; } return symlink(path, dest); } void str_make_ck_config_name(char *ret, const char *path, const char *progName) { if (!path || !ret || !progName) { return; } char *basec = strdup(path); char *bname = basename(basec); str_join_dirname_with_basename(ret, progName, bname); free(basec); } void str_join_dirname_with_basename(char *ret, const char *dirname, const char *basename) { if (!dirname || !ret || !basename) { return; } strcpy(ret, dirname); strcat(ret, "/"); strcat(ret, basename); } int str_is_empty(const char *s) { if (!s) { return 1; } while (*s != '\0') { if (!isspace((unsigned char)*s)) { return 0; } s++; } return 1; } char * swap_tilde_with_home(char *ret, const char *s, const char *home) { if (!ret || !s || !home) { return NULL; } ulong i; ulong homelen = strlen(home); if (s[0] == '~') { strcpy(ret, home); for (i = 1; i < strlen(s); i++) { ret[homelen - 1 + i] = s[i]; } return ret; } return NULL; } char * swap_home_with_tilde(char *ret, const char *s, const char *home) { if (!ret || !s || !home) { return NULL; } ulong i; ulong homelen = strlen(home); for (i = 0; i < strlen(home); i++) { if (s[i] != home[i]) { return NULL; } } /* s starts with $HOME */ strcpy(ret, "~"); for (i = homelen; i < strlen(s); i++) { ret[i + 1 - homelen] = s[i]; } return ret; } int util_own_grp_copy(const char *dest, const char *original) { if (!dest || !original) { return -1; } struct stat destbuf, origbuf; if (lstat(dest, &destbuf)) { sERR("error stating %s", dest) return -1; } if (stat(original, &origbuf)) { sERR("error stating %s", original) return -1; } if (destbuf.st_uid != origbuf.st_uid || destbuf.st_gid != origbuf.st_gid) { hLOG("Copying uid & gid: %s -> %s", original, dest); if (lchown(dest, origbuf.st_uid, origbuf.st_gid)) { sERR("Cannot change owner and group of %s", dest); return -1; } } return 0; } int util_is_link_owned_by_root(const char *link) { if (!link) { return 0; } struct stat buf; if (!lstat(link, &buf)) { if (buf.st_uid == (uid_t)0) { return 1; } } return 0; } int y_or_n_prompt() { char c; printf("[y/n] > "); c = (char)getchar(); if (c == 'y') { return 1; } return 0; } void decorate_entry(char *entry, int secret, int primary, const char *path) { if (primary) { strcat(entry, " [p]"); } if (secret) { strcat(entry, " [s]"); } /* root */ if (util_is_link_owned_by_root(path)) { strcat(entry, " [root]"); } }