1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
/**
* @file mime.c
*/
#include "spm.h"
/**
* Execute OS `file` command
* @param _filename path to file
* @return Process structure
*/
Process *file_command(const char *_filename) {
char *filename = strdup(_filename);
Process *proc_info = NULL;
char sh_cmd[PATH_MAX];
sh_cmd[0] = '\0';
#ifdef __APPLE__
const char *fmt_cmd = "file -I \"%s\"";
#else // GNU
const char *fmt_cmd = "file -E -i \"%s\"";
#endif
strchrdel(filename, "&;|");
sprintf(sh_cmd, fmt_cmd, filename);
shell(&proc_info, SHELL_OUTPUT, sh_cmd);
#ifdef __APPLE__
// Force BSD command to return non-zero when a file can't be found
const char *failmsg = ": cannot open";
if (strstr(proc_info->output, failmsg) != NULL) {
proc_info->returncode = 1;
}
#endif
free(filename);
return proc_info;
}
/**
* Execute the `file` command, parse its output, and return the data in a `Mime` structure
* @param filename path to file
* @return Mime structure
*/
Mime *file_mimetype(const char *filename) {
char **output = NULL;
char **parts = NULL;
Mime *type = NULL;
Process *proc = file_command(filename);
if (proc->returncode != 0) {
return NULL;
}
output = split(proc->output, ":");
if (!output || output[1] == NULL) {
return NULL;
}
parts = split(output[1], ";");
if (!parts || !parts[0] || !parts[1]) {
return NULL;
}
char *what = strdup(parts[0]);
what = lstrip(what);
char *charset = strdup(strchr(parts[1], '=') + 1);
charset = lstrip(charset);
charset[strlen(charset) - 1] = '\0';
char *origin = strdup(realpath(filename, NULL));
type = (Mime *)calloc(1, sizeof(Mime));
type->origin = origin;
type->type = strdup(what);
type->charset = strdup(charset);
split_free(output);
split_free(parts);
return type;
}
/**
* Free a `Mime` structure
* @param m
*/
void mime_free(Mime *m) {
if (m != NULL) {
free(m->origin);
free(m->type);
free(m->charset);
free(m);
}
}
/**
* Determine if a file is a text file
* @param filename
* @return yes=1, no=0
*/
int file_is_text(const char *filename) {
int result = 0;
char *path = normpath(filename);
Mime *type = file_mimetype(path);
if (startswith(type->type, "text/") == 0) {
result = 1;
}
free(path);
mime_free(type);
return result;
}
/**
* Determine if a file is a binary data file
* @param filename
* @return yes=1, no=0
*/
int file_is_binary(const char *filename) {
int result = 0;
char *path = normpath(filename);
Mime *type = file_mimetype(path);
if (startswith(type->type, "application/") == 0 && strcmp(type->charset, "binary") == 0) {
result = 1;
}
free(path);
mime_free(type);
return result;
}
|