ssnail

crappy and opinionated static site generator
git clone https://git.e1e0.net/ssnail.git
Log | Files | Refs | README | LICENSE

helpers.c (4700B)


      1 /*
      2  * Copyright (c) 2020 Paco Esteban <paco@e1e0.net>
      3  *
      4  * Permission to use, copy, modify, and distribute this software for any
      5  * purpose with or without fee is hereby granted, provided that the above
      6  * copyright notice and this permission notice appear in all copies.
      7  *
      8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
      9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     15 */
     16 
     17 #include <sys/stat.h>
     18 #include <sys/syslimits.h>
     19 
     20 #include <errno.h>
     21 #include <stdio.h>
     22 #include <stdlib.h>
     23 #include <string.h>
     24 
     25 #include "ssnail_error.h"
     26 #include "helpers.h"
     27 
     28 char *
     29 build_full_path(char *dir, char *file)
     30 {
     31 	size_t	 n = 0;
     32 	char	*fullpath = NULL, separator[2] = "";
     33 
     34 	/* if user input does not have trailing slash, add it */
     35 	if (dir[strlen(dir)-1] != '/')
     36 		n = strlcpy(separator, "/", sizeof(separator));
     37 	if (n >= sizeof(separator))
     38 		return NULL;
     39 
     40 	n = asprintf(&fullpath, "%s%s%s", dir, separator, file);
     41 	if ((n < 0) || (n > PATH_MAX)) {
     42 		return NULL;
     43 	}
     44 
     45 	return fullpath;
     46 }
     47 
     48 const struct ssnail_error *
     49 copy_file(const char *source_file, const char *dest_file, int force)
     50 {
     51 	FILE		*src, *dst;
     52 	struct		 stat st;
     53 	long long	 src_mtime, dst_mtime;
     54 
     55 	if (stat(source_file, &st) == -1)
     56 		return ssnail_error_from_errno("cp stat src");
     57 	src_mtime = st.st_mtim.tv_sec;
     58 
     59 	if (stat(dest_file, &st) == -1) { /* dst file does not have to exist */
     60 		if (errno != ENOENT)
     61 			return ssnail_error_from_errno("cp stat dst");
     62 		dst_mtime = 0;
     63 	} else {
     64 		dst_mtime = st.st_mtim.tv_sec;
     65 	}
     66 
     67 	if ((src_mtime > dst_mtime) || force) {
     68 		if ((src = fopen(source_file, "rb")) == NULL)
     69 			return ssnail_error_from_errno("cp fopen src");
     70 		if ((dst = fopen(dest_file, "wb")) == NULL)
     71 			return ssnail_error_from_errno("cp fopen dst");
     72 
     73 		printf("copying %s --> %s\n", source_file, dest_file);
     74 		size_t rcnt, wcnt;
     75 		unsigned char buff[4096];
     76 		do {
     77 			rcnt = fread(buff, 1, sizeof(buff), src);
     78 			if (rcnt) {
     79 				wcnt = fwrite(buff, 1, rcnt, dst);
     80 			} else  {
     81 				wcnt = 0;
     82 			}
     83 		} while ((rcnt > 0) && (rcnt == wcnt));
     84 		if (wcnt)
     85 			return ssnail_error_msg(2, "cp");
     86 
     87 		if (fclose(src) != 0)
     88 			return ssnail_error_from_errno("close src");
     89 		if (fclose(dst) != 0)
     90 			return ssnail_error_from_errno("close dst");
     91 	}
     92 
     93 	return NULL;
     94 }
     95 
     96 const char *
     97 get_filename_ext(const char *filename)
     98 {
     99 	const char *dot = strrchr(filename, '.');
    100 	if(!dot || dot == filename)
    101 		return "";
    102 	return dot + 1;
    103 }
    104 
    105 int
    106 load_from_file(char **buffer, char *path)
    107 {
    108 	long length = -1;
    109 	FILE *f = NULL;
    110 
    111 	if ((f = fopen(path, "r")) == NULL)
    112 		return 0;
    113 
    114 	if (f) {
    115 		/* Go to the end of the file.  Record it's length, and return to
    116 		 * the start
    117 		 */
    118 		if (fseek(f, 0, SEEK_END) == -1)
    119 			return 0;
    120 		if ((length = ftell(f)) == -1)
    121 			return 0;
    122 		if (fseek(f, 0, SEEK_SET) == -1)
    123 			return 0;
    124 
    125 		*buffer = malloc(length + 1);
    126 		if (*buffer == NULL)
    127 			return 0;
    128 		fread(*buffer, 1, length, f);
    129 		if (ferror(f) != 0)
    130 			return 0;
    131 
    132 		if (fclose(f) != 0)
    133 			return 0;
    134 		/* add null terminator to string.
    135 		 * apparently this is not the same as:
    136 		 * *buffer[length] = '\0';
    137 		 * but I do not know why ...
    138 		 */
    139 		*(*buffer + length) = '\0';
    140 	}
    141 
    142 	return length + 1;
    143 }
    144 
    145 int
    146 str_rep(char **str, const char *old, const char *new)
    147 {
    148 	char	*r, *s = *str;
    149 	int	 i, cnt = 0;
    150 	int	 new_len = strlen(new);
    151 	int	 old_len = strlen(old);
    152 
    153 	if (new_len == 0 || old_len == 0)
    154 		return -1;
    155 
    156 	/* Counting the number of times old word
    157 	 * occur in the string
    158 	 */
    159 	for (i = 0; s[i] != '\0'; i++) {
    160 		if (strstr(&s[i], old) == &s[i]) {
    161 			cnt++;
    162 			/* Jumping to index after the old word. */
    163 			i += old_len - 1;
    164 		}
    165 	}
    166 
    167 	/* Making new string long enough */
    168 	r = (char *)malloc(i + cnt * (new_len - old_len) + 1);
    169 	if (!r) return -1;
    170 
    171 	i = 0;
    172 	while (*s) {
    173 		/*
    174 		 * compare the substring the old word
    175 		 * if found (pointers are equal), copy new word in 'i' position
    176 		 * of result.  Then increment by the lenght so we do not check
    177 		 * unnecessarily.
    178 		 */
    179 		if (strstr(s, old) == s) {
    180 			/*
    181 			 * On the original example it was done like this:
    182 			 * strcpy(&r[i], new);
    183 			 * I think there's no need to dereference and reference
    184 			 * again.
    185 			 */
    186 			strcpy(r+i, new);
    187 			i += new_len;
    188 			s += old_len;
    189 		} else  /* if not copy the char and increment pointers */
    190 			r[i++] = *s++;
    191 	}
    192 
    193 	r[i] = '\0';
    194 
    195 	free(*str);
    196 	s = NULL;
    197 
    198 	*str = r;
    199 
    200 	return 0;
    201 }