dotfiles

personal configuration files and scripts
git clone https://tongong.net/git/dotfiles.git
Log | Files | Refs | README

util.c (4431B)


      1 /* Copyright 2011 Bert Muennich
      2  *
      3  * This file is part of sxiv.
      4  *
      5  * sxiv is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License as published
      7  * by the Free Software Foundation; either version 2 of the License,
      8  * or (at your option) any later version.
      9  *
     10  * sxiv is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  * GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License
     16  * along with sxiv.  If not, see <http://www.gnu.org/licenses/>.
     17  */
     18 
     19 #include "sxiv.h"
     20 
     21 #include <stdlib.h>
     22 #include <string.h>
     23 #include <sys/types.h>
     24 #include <sys/stat.h>
     25 #include <unistd.h>
     26 #include <errno.h>
     27 
     28 const char *progname;
     29 
     30 void* emalloc(size_t size)
     31 {
     32 	void *ptr;
     33 	
     34 	ptr = malloc(size);
     35 	if (ptr == NULL)
     36 		error(EXIT_FAILURE, errno, NULL);
     37 	return ptr;
     38 }
     39 
     40 void* erealloc(void *ptr, size_t size)
     41 {
     42 	ptr = realloc(ptr, size);
     43 	if (ptr == NULL)
     44 		error(EXIT_FAILURE, errno, NULL);
     45 	return ptr;
     46 }
     47 
     48 char* estrdup(const char *s)
     49 {
     50 	char *d;
     51 	size_t n = strlen(s) + 1;
     52 
     53 	d = malloc(n);
     54 	if (d == NULL)
     55 		error(EXIT_FAILURE, errno, NULL);
     56 	memcpy(d, s, n);
     57 	return d;
     58 }
     59 
     60 void error(int eval, int err, const char* fmt, ...)
     61 {
     62 	va_list ap;
     63 
     64 	if (eval == 0 && options->quiet)
     65 		return;
     66 
     67 	fflush(stdout);
     68 	fprintf(stderr, "%s: ", progname);
     69 	va_start(ap, fmt);
     70 	if (fmt != NULL)
     71 		vfprintf(stderr, fmt, ap);
     72 	va_end(ap);
     73 	if (err != 0)
     74 		fprintf(stderr, "%s%s", fmt != NULL ? ": " : "", strerror(err));
     75 	fputc('\n', stderr);
     76 
     77 	if (eval != 0)
     78 		exit(eval);
     79 }
     80 
     81 void size_readable(float *size, const char **unit)
     82 {
     83 	const char *units[] = { "", "K", "M", "G" };
     84 	int i;
     85 
     86 	for (i = 0; i < ARRLEN(units) && *size > 1024.0; i++)
     87 		*size /= 1024.0;
     88 	*unit = units[MIN(i, ARRLEN(units) - 1)];
     89 }
     90 
     91 int r_opendir(r_dir_t *rdir, const char *dirname, bool recursive)
     92 {
     93 	if (*dirname == '\0')
     94 		return -1;
     95 
     96 	if ((rdir->dir = opendir(dirname)) == NULL) {
     97 		rdir->name = NULL;
     98 		rdir->stack = NULL;
     99 		return -1;
    100 	}
    101 
    102 	rdir->stcap = 512;
    103 	rdir->stack = (char**) emalloc(rdir->stcap * sizeof(char*));
    104 	rdir->stlen = 0;
    105 
    106 	rdir->name = (char*) dirname;
    107 	rdir->d = 0;
    108 	rdir->recursive = recursive;
    109 
    110 	return 0;
    111 }
    112 
    113 int r_closedir(r_dir_t *rdir)
    114 {
    115 	int ret = 0;
    116 
    117 	if (rdir->stack != NULL) {
    118 		while (rdir->stlen > 0)
    119 			free(rdir->stack[--rdir->stlen]);
    120 		free(rdir->stack);
    121 		rdir->stack = NULL;
    122 	}
    123 
    124 	if (rdir->dir != NULL) {
    125 		if ((ret = closedir(rdir->dir)) == 0)
    126 			rdir->dir = NULL;
    127 	}
    128 
    129 	if (rdir->d != 0) {
    130 		free(rdir->name);
    131 		rdir->name = NULL;
    132 	}
    133 
    134 	return ret;
    135 }
    136 
    137 char* r_readdir(r_dir_t *rdir, bool skip_dotfiles)
    138 {
    139 	size_t len;
    140 	char *filename;
    141 	struct dirent *dentry;
    142 	struct stat fstats;
    143 
    144 	while (true) {
    145 		if (rdir->dir != NULL && (dentry = readdir(rdir->dir)) != NULL) {
    146 			if (dentry->d_name[0] == '.') {
    147 				if (skip_dotfiles)
    148 					continue;
    149 				if (dentry->d_name[1] == '\0')
    150 					continue;
    151 				if (dentry->d_name[1] == '.' && dentry->d_name[2] == '\0')
    152 					continue;
    153 			}
    154 
    155 			len = strlen(rdir->name) + strlen(dentry->d_name) + 2;
    156 			filename = (char*) emalloc(len);
    157 			snprintf(filename, len, "%s%s%s", rdir->name,
    158 			         rdir->name[strlen(rdir->name)-1] == '/' ? "" : "/",
    159 			         dentry->d_name);
    160 
    161 			if (stat(filename, &fstats) < 0)
    162 				continue;
    163 			if (S_ISDIR(fstats.st_mode)) {
    164 				/* put subdirectory on the stack */
    165 				if (rdir->stlen == rdir->stcap) {
    166 					rdir->stcap *= 2;
    167 					rdir->stack = (char**) erealloc(rdir->stack,
    168 					                                rdir->stcap * sizeof(char*));
    169 				}
    170 				rdir->stack[rdir->stlen++] = filename;
    171 				continue;
    172 			}
    173 			return filename;
    174 		}
    175 		
    176 		if (rdir->recursive && rdir->stlen > 0) {
    177 			/* open next subdirectory */
    178 			closedir(rdir->dir);
    179 			if (rdir->d != 0)
    180 				free(rdir->name);
    181 			rdir->name = rdir->stack[--rdir->stlen];
    182 			rdir->d = 1;
    183 			if ((rdir->dir = opendir(rdir->name)) == NULL)
    184 				error(0, errno, "%s", rdir->name);
    185 			continue;
    186 		}
    187 		/* no more entries */
    188 		break;
    189 	}
    190 	return NULL;
    191 }
    192 
    193 int r_mkdir(char *path)
    194 {
    195 	char c, *s = path;
    196 	struct stat st;
    197 
    198 	while (*s != '\0') {
    199 		if (*s == '/') {
    200 			s++;
    201 			continue;
    202 		}
    203 		for (; *s != '\0' && *s != '/'; s++);
    204 		c = *s;
    205 		*s = '\0';
    206 		if (mkdir(path, 0755) == -1)
    207 			if (errno != EEXIST || stat(path, &st) == -1 || !S_ISDIR(st.st_mode))
    208 				return -1;
    209 		*s = c;
    210 	}
    211 	return 0;
    212 }
    213