hermes

HTTP GET/HEAD-only web server for static content.
git clone https://git.francescosaccone.com/hermes
Log | Files | Refs | README | LICENSE

file.c (2683B)


      1 #include "file.h"
      2 
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <string.h>
      6 #include <sys/stat.h>
      7 #include <unistd.h>
      8 
      9 char *
     10 get_mime_type_from_extension(char *extension) {
     11 	char *default_type = "application/octet-stream";
     12 	size_t i,
     13 	       number_of_types = sizeof(mime_types)
     14 	                         / sizeof(mime_types[0]);
     15 
     16 	for (i = 0; i < number_of_types; i++) {
     17 		if (strcmp(mime_types[i].extension, extension) == 0) {
     18 			return mime_types[i].type;
     19 		}
     20 	}
     21 
     22 	return default_type;
     23 }
     24 
     25 int
     26 is_file_readable(char *path) {
     27 	struct stat file_stat;
     28 
     29 	if (stat(path, &file_stat) != 0) {
     30 		return 0;
     31 	}
     32 
     33 	if (!S_ISREG(file_stat.st_mode)) {
     34 		return 0;
     35 	}
     36 
     37 	if (access(path, R_OK) != 0) {
     38 		return 0;
     39 	};
     40 
     41 	return 1;
     42 }
     43 
     44 char *
     45 get_normalised_path(char *path) {
     46 	char *normalised;
     47 	int i,
     48 	    j;
     49 
     50 	if (path == NULL) {
     51 		return path;
     52 	}
     53 
     54 	normalised = malloc(strlen(path) + 1);
     55 
     56 	if (normalised == NULL) {
     57 		return normalised;
     58 	}
     59 
     60 	j = 0;
     61 	for (i = 0; path[i] != '\0'; i++) {
     62 		if (path[i] != '/' ||
     63 		    /* In the following conditions, we have path[i] == '/'. */
     64 		    i == 0 ||                /* Keep leading slash */
     65 		    path[i - 1] != '/' ||    /* No continous slashes */
     66 		    path[i + 1] != '\0') {   /* No trailing slash */
     67 			normalised[j] = path[i];
     68 			j++;
     69 		}
     70 	}
     71 
     72 	normalised[j] = '\0';
     73 
     74 	return normalised;
     75 }
     76 
     77 char *
     78 get_file_name(char *path) {
     79 	char *last_slash = strrchr(path, '/'),
     80 	     *character_after_last_slash = last_slash + sizeof(char);
     81 
     82 	if (last_slash == NULL) {
     83 		/* If no slash occurs, the file name is the actual path */
     84 		return path;
     85 	}
     86 
     87 	if (*character_after_last_slash == '\0') {
     88 		/* If path ends in '/', the file name will be considered
     89 		   empty */
     90 		return "";
     91 	}
     92 
     93 	return character_after_last_slash;
     94 }
     95 
     96 char *
     97 get_file_extension(char *path) {
     98 	char *file_name = get_file_name(path),
     99 	     *last_dot = strrchr(file_name, '.');
    100 
    101 	if (last_dot == NULL) {
    102 		return "";
    103 	}
    104 
    105 	return last_dot + sizeof(char);
    106 }
    107 
    108 struct file_content
    109 get_file_content(char *path) {
    110 	struct file_content result = { NULL, 0 };
    111 	FILE *file = fopen(path, "rb");
    112 	long file_size;
    113 	size_t bytes_read;
    114 
    115 	if (file == NULL) {
    116 		return result;
    117 	}
    118 
    119 	/* Move the file pointer to the end of the file */
    120 	fseek(file, 0, SEEK_END);
    121 	/* Get the size */
    122 	file_size = ftell(file);
    123 	/* Come back at the start of the file */
    124 	fseek(file, 0, SEEK_SET);
    125 
    126 	result.content = malloc(file_size + 1);
    127 
    128 	if (!result.content) {
    129 		fclose(file);
    130 		return result;
    131 	}
    132 
    133 	bytes_read = fread(result.content, 1, file_size, file);
    134 
    135 	/* 'result' gets written here. Before this, it remained { NULL, 0 }. */
    136 	result.content[bytes_read] = '\0';
    137 	result.length = bytes_read;
    138 
    139 	fclose(file);
    140 
    141 	return result;
    142 }