aboutsummaryrefslogblamecommitdiffstats
path: root/src/ckutil.c
blob: fde5e24035062afe8e805d1ac701e89ce4c248bc (plain) (tree)
1
2
3
4
5
6
7
8
9
10









                                                                                
                  



                         



                     


                     

                                   


              








                      
                                                       


                          



                              
                

                            


           
                                       


              





                                       
                                         


              







                             
                                   


              

                    

                                                        


                       




                                                
                                                        














                                                           


                       


                             
                                                         
                                                    


                                   


                                
                                                       




                                                                   


                                      





                                 


             







                                      
 
                                                                         
                            
                


                               




                                     
               

   
              

 
                                                                         
                            
                



                               

                                      
                  






                                         
             

 






















                                                               












                                                  











                       
/* 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 <ctype.h>
#include <dirent.h>
#include <fcntl.h>
#include <libgen.h>
#include <sys/sendfile.h>
#include <sys/stat.h>
#include <unistd.h>

#include "ckutil.h"
#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;
}