1 #include <sys/stat.h>
2 #include <stdio.h>
3 #include <stdint.h>
4 #include <stdlib.h>
5 #include <limits.h>
6 #include <errno.h>
7 #include <assert.h>
8 #include <string.h>
9 #include <dirent.h>
10 #include <ctype.h>
11 #ifndef __MINGW32__
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <pwd.h>
15 #include <unistd.h>
16 #ifdef HAVE_GLOB_H
17 #include <glob.h>
18 #endif
19 #else
20 #include <io.h>
21 #include <shlobj.h>
22 #endif
23 #ifdef WITH_LIBARCHIVE
24 #include <archive.h>
25 /* For backward compatibility. */
26 #if ARCHIVE_VERSION_NUMBER < 3001000
27 #define archive_read_free(...) \
28 	archive_read_finish(__VA_ARGS__)
29 #define archive_read_support_filter_all(...) \
30 	archive_read_support_compression_all(__VA_ARGS__)
31 #endif
32 #endif
33 #include "system.h"
34 
35 #ifdef __MINGW32__
36 #define mkdir(a, b) mkdir(a)
37 #if MAX_PATH < PATH_MAX
38 #error MAX_PATH < PATH_MAX. You should use MAX_PATH.
39 #endif
40 #endif
41 
fopen_mode(unsigned int mode)42 static const char *fopen_mode(unsigned int mode)
43 {
44 	static const char *modes[4][2] = {
45 		{ "ab", "a" },
46 		{ "w+b", "w+" },
47 		{ "rb", "r" },
48 		{ NULL, NULL }
49 	};
50 	const char *(*cmode)[2] = &modes[0];
51 
52 	if (!(mode & DGEN_APPEND)) {
53 		++cmode;
54 		if (!(mode & DGEN_WRITE)) {
55 			++cmode;
56 			if (!(mode & DGEN_READ))
57 				++cmode;
58 		}
59 	}
60 	return (*cmode)[(!!(mode & DGEN_TEXT))];
61 }
62 
63 enum path_type {
64 	PATH_TYPE_UNSPECIFIED,
65 	PATH_TYPE_RELATIVE,
66 	PATH_TYPE_ABSOLUTE
67 };
68 
69 #ifdef __MINGW32__
70 
71 /**
72  * Check whether a path is absolute or relative.
73  *
74  * Examples:
75  * /foo/bar, \\foo\\bar, c:/foo/bar are absolute,
76  * ./foo/bar, ., .., are relative.
77  *
78  * @param[in] path Path to parse.
79  * @param len Length of path.
80  * @return Path type (PATH_TYPE_ABSOLUTE, PATH_TYPE_RELATIVE or
81  * PATH_TYPE_UNSPECIFIED).
82  */
path_type(const char * path,size_t len)83 enum path_type path_type(const char *path, size_t len)
84 {
85 	if ((len == 0) || (path[0] == '\0'))
86 		return PATH_TYPE_UNSPECIFIED;
87 	if ((path[0] == '\\') || (path[0] == '/'))
88 		return PATH_TYPE_ABSOLUTE;
89 	if ((path[0] == '.') &&
90 	    (((len == 1) ||
91 	      (path[1] == '\0') || (path[1] == '\\') || (path[1] == '/')) ||
92 	     ((path[1] == '.') &&
93 	      ((len == 2) ||
94 	       (path[2] == '\0') || (path[2] == '\\') || (path[2] == '/')))))
95 		return PATH_TYPE_RELATIVE;
96 	do {
97 		if (*(++path) == ':')
98 			return PATH_TYPE_ABSOLUTE;
99 		--len;
100 	}
101 	while ((len) && (*path != '\0') && (*path != '\\') && (*path != '/'));
102 	return PATH_TYPE_UNSPECIFIED;
103 }
104 
105 #else /* __MINGW32__ */
106 
107 /**
108  * Check whether a path is absolute or relative.
109  *
110  * Examples:
111  * /foo/bar, \\foo\\bar are absolute,
112  * ./foo/bar, ., .., are relative.
113  *
114  * @param[in] path Path to parse.
115  * @param len Length of path.
116  * @return Path type (PATH_TYPE_ABSOLUTE, PATH_TYPE_RELATIVE or
117  * PATH_TYPE_UNSPECIFIED).
118  */
path_type(const char * path,size_t len)119 enum path_type path_type(const char *path, size_t len)
120 {
121 	if ((len == 0) || (path[0] == '\0'))
122 		return PATH_TYPE_UNSPECIFIED;
123 	if (path[0] == '/')
124 		return PATH_TYPE_ABSOLUTE;
125 	if ((path[0] == '.') &&
126 	    (((len == 1) || (path[1] == '\0') || (path[1] == '/')) ||
127 	     ((path[1] == '.') &&
128 	      ((len == 2) || (path[2] == '\0') || (path[2] == '/')))))
129 		return PATH_TYPE_RELATIVE;
130 	return PATH_TYPE_UNSPECIFIED;
131 }
132 
133 #endif /* __MINGW32__ */
134 
135 /**
136  * Return user's home directory.
137  * The returned string doesn't have a trailing '/' and must be freed using
138  * free() (unless "buf" is provided).
139  *
140  * @param[in,out] buf Used to store path in. If NULL, memory is allocated.
141  * @param[in,out] size Size of "buf" when provided, then the returned path
142  * size.
143  * @return User's home directory (either as "buf" or a new buffer),
144  * NULL in case of error.
145  */
dgen_userdir(char * buf,size_t * size)146 char *dgen_userdir(char *buf, size_t *size)
147 {
148 	char *path;
149 	size_t sz_dir;
150 	size_t sz;
151 #ifndef __MINGW32__
152 	struct passwd *pwd = getpwuid(geteuid());
153 
154 	if ((pwd == NULL) || (pwd->pw_dir == NULL))
155 		return NULL;
156 	sz_dir = strlen(pwd->pw_dir);
157 #endif
158 	if (buf != NULL) {
159 		sz = *size;
160 #ifdef __MINGW32__
161 		if (sz < PATH_MAX)
162 			return NULL;
163 #else
164 		if (sz < (sz_dir + 1))
165 			return NULL;
166 #endif
167 		path = buf;
168 	}
169 	else {
170 #ifdef __MINGW32__
171 		sz = PATH_MAX;
172 #else
173 		sz = (sz_dir + 1);
174 #endif
175 		if ((path = malloc(sz)) == NULL)
176 			return NULL;
177 	}
178 #ifndef __MINGW32__
179 	strncpy(path, pwd->pw_dir, sz_dir);
180 #else
181 	if (SHGetFolderPath(NULL, (CSIDL_PROFILE | CSIDL_FLAG_CREATE),
182 			    0, 0, path) != S_OK) {
183 		if (buf == NULL)
184 			free(path);
185 		return NULL;
186 	}
187 	sz_dir = strlen(path);
188 	if (sz < (sz_dir + 1)) {
189 		if (buf == NULL)
190 			free(path);
191 		return NULL;
192 	}
193 #endif
194 	path[sz_dir] = '\0';
195 	if (size != NULL)
196 		*size = sz_dir;
197 	return path;
198 }
199 
200 /**
201  * Return DGen's home directory with an optional subdirectory (or file).
202  * The returned string doesn't have a trailing '/' and must be freed using
203  * free() (unless "buf" is provided).
204  *
205  * @param[in,out] buf Buffer to store result in. If NULL, memory is allocated.
206  * @param[in,out] size Size of "buf" when provided, then the returned path
207  * size.
208  * @param[in] sub NUL-terminated string to append to the path.
209  * @return DGen's home directory (either as "buf" or a new buffer),
210  * NULL in case of error.
211  */
dgen_dir(char * buf,size_t * size,const char * sub)212 char *dgen_dir(char *buf, size_t *size, const char *sub)
213 {
214 	char *path;
215 	size_t sz_dir;
216 	size_t sz_sub;
217 	const size_t sz_bd = strlen(DGEN_BASEDIR);
218 	size_t sz;
219 #ifndef __MINGW32__
220 	struct passwd *pwd = getpwuid(geteuid());
221 
222 	if ((pwd == NULL) || (pwd->pw_dir == NULL))
223 		return NULL;
224 	sz_dir = strlen(pwd->pw_dir);
225 #endif
226 	if (sub != NULL)
227 		sz_sub = strlen(sub);
228 	else
229 		sz_sub = 0;
230 	if (buf != NULL) {
231 		sz = *size;
232 #ifdef __MINGW32__
233 		if (sz < PATH_MAX)
234 			return NULL;
235 #else
236 		if (sz < (sz_dir + 1 + sz_bd + !!sz_sub + sz_sub + 1))
237 			return NULL;
238 #endif
239 		path = buf;
240 	}
241 	else {
242 #ifdef __MINGW32__
243 		sz = PATH_MAX;
244 #else
245 		sz = (sz_dir + 1 + sz_bd + !!sz_sub + sz_sub + 1);
246 #endif
247 		if ((path = malloc(sz)) == NULL)
248 			return NULL;
249 	}
250 #ifndef __MINGW32__
251 	strncpy(path, pwd->pw_dir, sz_dir);
252 #else
253 	if (SHGetFolderPath(NULL, (CSIDL_APPDATA | CSIDL_FLAG_CREATE),
254 			    0, 0, path) != S_OK) {
255 		if (buf == NULL)
256 			free(path);
257 		return NULL;
258 	}
259 	sz_dir = strlen(path);
260 	if (sz < (sz_dir + 1 + sz_bd + !!sz_sub + sz_sub + 1)) {
261 		if (buf == NULL)
262 			free(path);
263 		return NULL;
264 	}
265 #endif
266 	path[(sz_dir++)] = DGEN_DIRSEP[0];
267 	memcpy(&path[sz_dir], DGEN_BASEDIR, sz_bd);
268 	sz_dir += sz_bd;
269 	if (sz_sub) {
270 		path[(sz_dir++)] = DGEN_DIRSEP[0];
271 		memcpy(&path[sz_dir], sub, sz_sub);
272 		sz_dir += sz_sub;
273 	}
274 	path[sz_dir] = '\0';
275 	if (size != NULL)
276 		*size = sz_dir;
277 	return path;
278 }
279 
280 /**
281  * Open a file relative to DGen's home directory (when "relative" is NULL or
282  * path_type(relative) returns PATH_TYPE_UNSPECIFIED) and create the directory
283  * hierarchy if necessary, unless the file name is already relative to
284  * something or found in the current directory if mode contains DGEN_CURRENT.
285  *
286  * @param[in] relative Subdirectory to look in.
287  * @param[in] file File name to open.
288  * @param mode Mode flags to use (DGEN_READ, DGEN_WRITE and others).
289  * @return File pointer, or NULL in case of error.
290  * @see dgen_freopen()
291  * @see system.h
292  */
dgen_fopen(const char * relative,const char * file,unsigned int mode)293 FILE *dgen_fopen(const char *relative, const char *file, unsigned int mode)
294 {
295 	return dgen_freopen(relative, file, mode, NULL);
296 }
297 
298 /**
299  * @see dgen_fopen()
300  */
dgen_freopen(const char * relative,const char * file,unsigned int mode,FILE * f)301 FILE *dgen_freopen(const char *relative, const char *file, unsigned int mode,
302 		   FILE *f)
303 {
304 	size_t size;
305 	size_t file_size;
306 	char *tmp;
307 	int e = errno;
308 	const char *fmode = fopen_mode(mode);
309 	char *path = NULL;
310 
311 	if ((file == NULL) || (file[0] == '\0') || (fmode == NULL))
312 		goto error;
313 	/*
314 	  Try to open the file in the current directory if DGEN_CURRENT
315 	  is specified.
316 	*/
317 	if (mode & DGEN_CURRENT) {
318 		FILE *fd;
319 
320 		if (f == NULL)
321 			fd = fopen(file, fmode);
322 		else
323 			fd = freopen(file, fmode, f);
324 		if (fd != NULL)
325 			return fd;
326 	}
327 	if (path_type(file, ~0u) != PATH_TYPE_UNSPECIFIED)
328 		size = 0;
329 	else if ((relative == NULL) ||
330 		 (path_type(relative, ~0u) == PATH_TYPE_UNSPECIFIED)) {
331 		if ((path = dgen_dir(NULL, &size, relative)) == NULL)
332 			goto error;
333 	}
334 	else {
335 		if ((path = strdup(relative)) == NULL)
336 			goto error;
337 		size = strlen(path);
338 	}
339 	if ((mode & (DGEN_WRITE | DGEN_APPEND)) && (path != NULL))
340 		mkdir(path, 0777); /* XXX make that recursive */
341 	file_size = strlen(file);
342 	if ((tmp = realloc(path, (size + !!size + file_size + 1))) == NULL)
343 		goto error;
344 	path = tmp;
345 	if (size)
346 		path[(size++)] = DGEN_DIRSEP[0];
347 	memcpy(&path[size], file, file_size);
348 	size += file_size;
349 	path[size] = '\0';
350 	errno = e;
351 	if (f == NULL)
352 		f = fopen(path, fmode);
353 	else
354 		f = freopen(path, fmode, f);
355 	e = errno;
356 	free(path);
357 	errno = e;
358 	return f;
359 error:
360 	free(path);
361 	errno = EACCES;
362 	return NULL;
363 }
364 
365 /**
366  * Return the base name in path, like basename() but without allocating
367  * anything nor modifying the "path" argument.
368  *
369  * @param[in] path Path to extract the last component from.
370  * @return Last component from "path".
371  */
dgen_basename(const char * path)372 const char *dgen_basename(const char *path)
373 {
374 	char *tmp;
375 
376 	while ((tmp = strpbrk(path, DGEN_DIRSEP)) != NULL)
377 		path = (tmp + 1);
378 	return path;
379 }
380 
381 #define CHUNK_SIZE BUFSIZ
382 
383 struct chunk {
384 	size_t size;
385 	struct chunk *next;
386 	struct chunk *prev;
387 	uint8_t data[];
388 };
389 
390 /**
391  * Unload pointer returned by load().
392  *
393  * @param[in] data Pointer to unload.
394  */
unload(uint8_t * data)395 void unload(uint8_t *data)
396 {
397 	struct chunk *chunk = ((struct chunk *)data - 1);
398 
399 	assert(chunk->next == chunk);
400 	assert(chunk->prev == chunk);
401 	free(chunk);
402 }
403 
404 #ifdef HAVE_FTELLO
405 #define FTELL(f) ftello(f)
406 #define FSEEK(f, o, w) fseeko((f), (o), (w))
407 #define FOFFT off_t
408 #else
409 #define FTELL(f) ftell(f)
410 #define FSEEK(f, o, w) fseek((f), (o), (w))
411 #define FOFFT long
412 #endif
413 
414 /**
415  * Call this when you're done with your file.
416  *
417  * @param[in,out] context Context returned by load().
418  */
load_finish(void ** context)419 void load_finish(void **context)
420 {
421 #ifdef WITH_LIBARCHIVE
422 	struct archive *archive = *context;
423 
424 	if (archive != NULL)
425 		archive_read_free(archive);
426 #endif
427 	*context = NULL;
428 }
429 
430 /**
431  * Return the remaining file size from the current file offset.
432  *
433  * @param[in] file File pointer.
434  */
load_size(FILE * file)435 static size_t load_size(FILE *file)
436 {
437 	FOFFT old = FTELL(file);
438 	FOFFT pos;
439 	size_t ret = 0;
440 
441 	if ((old == (FOFFT)-1) ||
442 	    (FSEEK(file, 0, SEEK_END) == -1))
443 		return 0;
444 	if (((pos = FTELL(file)) != (FOFFT)-1) && (pos >= old))
445 		ret = (size_t)(pos - old);
446 	FSEEK(file, old, SEEK_SET);
447 	return ret;
448 }
449 
450 /**
451  * Allocate a buffer and stuff the file inside using transparent decompression
452  * if libarchive is available. If file_size is non-NULL, store the final size
453  * there. If max_size is nonzero, refuse to load anything larger.
454  * In case the returned value is NULL, errno should contain the error.
455  *
456  * If an error is returned but errno is 0, EOF has been reached.
457  *
458  * @param[in,out] context On first call of load() this should point to NULL.
459  * @param[out] file_size Final size.
460  * @param[in] file File pointer to load data from.
461  * @param max_size If nonzero, refuse to load anything larger.
462  * @return Buffer containing loaded data.
463  */
load(void ** context,size_t * file_size,FILE * file,size_t max_size)464 uint8_t *load(void **context,
465 	      size_t *file_size, FILE *file, size_t max_size)
466 {
467 	size_t pos;
468 	size_t size = 0;
469 	struct chunk *chunk;
470 	struct chunk head = { 0, &head, &head };
471 	size_t chunk_size = load_size(file);
472 	int error = 0;
473 #ifdef WITH_LIBARCHIVE
474 	struct archive *archive = *context;
475 	struct archive_entry *archive_entry;
476 
477 	if (archive != NULL)
478 		goto init_ok;
479 	archive = archive_read_new();
480 	*context = archive;
481 	if (archive == NULL) {
482 		error = ENOMEM;
483 		goto error;
484 	}
485 	archive_read_support_filter_all(archive);
486 	archive_read_support_format_all(archive);
487 	archive_read_support_format_raw(archive);
488 	if (archive_read_open_FILE(archive, file) != ARCHIVE_OK) {
489 		error = EIO;
490 		goto error;
491 	}
492 init_ok:
493 	switch (archive_read_next_header(archive, &archive_entry)) {
494 	case ARCHIVE_OK:
495 		break;
496 	case ARCHIVE_EOF:
497 		error = 0;
498 		goto error;
499 	default:
500 		error = EIO;
501 		goto error;
502 	}
503 #else
504 	*context = (void *)0xffff;
505 #endif
506 	if (chunk_size == 0)
507 		chunk_size = CHUNK_SIZE;
508 	else if ((max_size != 0) && (chunk_size > max_size))
509 		chunk_size = max_size;
510 	while (1) {
511 		pos = 0;
512 		chunk = malloc(sizeof(*chunk) + chunk_size);
513 		if (chunk == NULL) {
514 			error = errno;
515 			goto error;
516 		}
517 		chunk->size = chunk_size;
518 		chunk->next = &head;
519 		chunk->prev = head.prev;
520 		chunk->prev->next = chunk;
521 		head.prev = chunk;
522 		do {
523 			size_t i;
524 #ifdef WITH_LIBARCHIVE
525 			ssize_t j;
526 
527 			j = archive_read_data(archive, &chunk->data[pos],
528 					      (chunk->size - pos));
529 			/*
530 			  Don't bother with ARCHIVE_WARN and ARCHIVE_RETRY,
531 			  consider any negative value an error.
532 			*/
533 			if (j < 0) {
534 				error = EIO;
535 				goto error;
536 			}
537 			i = (size_t)j;
538 #else
539 			i = fread(&chunk->data[pos], 1, (chunk->size - pos),
540 				  file);
541 #endif
542 			if (i == 0) {
543 				chunk->size = pos;
544 #ifndef WITH_LIBARCHIVE
545 				if (ferror(file)) {
546 					error = EIO;
547 					goto error;
548 				}
549 				assert(feof(file));
550 #endif
551 				goto process;
552 			}
553 			pos += i;
554 			size += i;
555 			if ((max_size != 0) && (size > max_size)) {
556 				error = EFBIG;
557 				goto error;
558 			}
559 		}
560 		while (pos != chunk->size);
561 		chunk_size = CHUNK_SIZE;
562 	}
563 process:
564 	chunk = realloc(head.next, (sizeof(*chunk) + size));
565 	if (chunk == NULL) {
566 		error = errno;
567 		goto error;
568 	}
569 	chunk->next->prev = chunk;
570 	head.next = chunk;
571 	pos = chunk->size;
572 	chunk->size = size;
573 	chunk = chunk->next;
574 	while (chunk != &head) {
575 		struct chunk *next = chunk->next;
576 
577 		memcpy(&head.next->data[pos], chunk->data, chunk->size);
578 		pos += chunk->size;
579 		chunk->next->prev = chunk->prev;
580 		chunk->prev->next = chunk->next;
581 		free(chunk);
582 		chunk = next;
583 	}
584 	chunk = head.next;
585 	chunk->prev = chunk;
586 	chunk->next = chunk;
587 	if (file_size != NULL)
588 		*file_size = chunk->size;
589 	return chunk->data;
590 error:
591 #ifdef WITH_LIBARCHIVE
592 	load_finish(context);
593 #endif
594 	chunk = head.next;
595 	while (chunk != &head) {
596 		struct chunk *next = chunk->next;
597 
598 		free(chunk);
599 		chunk = next;
600 	}
601 	errno = error;
602 	return NULL;
603 }
604 
605 /**
606  * Free NULL-terminated list of strings and set source pointer to NULL.
607  * This function can skip a given number of indices (starting from 0)
608  * which won't be freed.
609  *
610  * @param[in,out] pppc Pointer to an array of strings.
611  * @param skip Number of indices to skip in *pppc[].
612  */
free_pppc(char *** pppc,size_t skip)613 static void free_pppc(char ***pppc, size_t skip)
614 {
615 	char **p = *pppc;
616 	size_t i;
617 
618 	if (p == NULL)
619 		return;
620 	*pppc = NULL;
621 	for (i = 0; (p[i] != NULL); ++i) {
622 		if (skip == 0)
623 			free(p[i]);
624 		else
625 			--skip;
626 	}
627 	free(p);
628 }
629 
630 /**
631  * Return a list of path names that match "len" characters of "path" on the
632  * file system, or NULL if none was found or if an error occured.
633  *
634  * @param[in] path Path name to match.
635  * @param len Number of characters in "path" to match.
636  * @return List of matching path names or NULL.
637  */
complete_path_simple(const char * path,size_t len)638 static char **complete_path_simple(const char *path, size_t len)
639 {
640 	size_t rlen;
641 	const char *cpl;
642 	char *root;
643 	struct dirent *dent;
644 	DIR *dir;
645 	char **ret = NULL;
646 	size_t ret_size = 256;
647 	size_t ret_used = 0;
648 	struct stat st;
649 
650 	if ((rlen = strlen(path)) < len)
651 		len = rlen;
652 	cpl = path;
653 	while (((root = strpbrk(cpl, DGEN_DIRSEP)) != NULL) &&
654 	       (root < (path + len)))
655 		cpl = (root + 1);
656 	rlen = (cpl - path);
657 	len -= rlen;
658 	if (rlen == 0) {
659 		path = "." DGEN_DIRSEP;
660 		rlen = 2;
661 	}
662 	if ((root = malloc(rlen + 1)) == NULL)
663 		return NULL;
664 	memcpy(root, path, rlen);
665 	root[rlen] = '\0';
666 	if (((dir = opendir(root)) == NULL) ||
667 	    ((ret = malloc(sizeof(*ret) * ret_size)) == NULL))
668 		goto error;
669 	ret[(ret_used++)] = NULL;
670 	while ((dent = readdir(dir)) != NULL) {
671 		size_t i;
672 		char *t;
673 
674 		if ((cpl[0] != '\0') && (strncmp(cpl, dent->d_name, len)))
675 			continue;
676 		/* Remove "." and ".." entries. */
677 		if ((dent->d_name[0] == '.') &&
678 		    ((dent->d_name[1] == '\0') ||
679 		     ((dent->d_name[1] == '.') && (dent->d_name[2] == '\0'))))
680 			continue;
681 		if (ret_used == ret_size) {
682 			char **rt;
683 
684 			ret_size *= 2;
685 			if ((rt = realloc(ret,
686 					  (sizeof(*rt) * ret_size))) == NULL)
687 				break;
688 			ret = rt;
689 		}
690 		i = strlen(dent->d_name);
691 		/* Allocate one extra char in case it's a directory. */
692 		if ((t = malloc(rlen + i + 1 + 1)) == NULL)
693 			break;
694 		memcpy(t, root, rlen);
695 		memcpy(&t[rlen], dent->d_name, i);
696 		t[(rlen + i)] = '\0';
697 		if ((stat(t, &st) != -1) && (S_ISDIR(st.st_mode))) {
698 			t[(rlen + (i++))] = DGEN_DIRSEP[0];
699 			t[(rlen + i)] = '\0';
700 		}
701 		for (i = 0; (ret[i] != NULL); ++i)
702 			if (strcmp(dent->d_name, &ret[i][rlen]) < 0)
703 				break;
704 		memmove(&ret[(i + 1)], &ret[i],
705 			(sizeof(*ret) * (ret_used - i)));
706 		ret[i] = t;
707 		++ret_used;
708 	}
709 	closedir(dir);
710 	free(root);
711 	if (ret[0] != NULL)
712 		return ret;
713 	free(ret);
714 	return NULL;
715 error:
716 	if (dir != NULL)
717 		closedir(dir);
718 	free(root);
719 	if (ret != NULL) {
720 		while (*ret != NULL)
721 			free(*(ret++));
722 		free(ret);
723 	}
724 	return NULL;
725 }
726 
727 #if defined(HAVE_GLOB_H) && !defined(__MINGW32__)
728 
729 #define COMPLETE_USERDIR_TILDE 0x01
730 #define COMPLETE_USERDIR_EXACT 0x02
731 #define COMPLETE_USERDIR_ALL 0x04
732 
733 /**
734  * Return the list of home directories that match "len" characters of a
735  * user's name ("prefix").
736  * COMPLETE_USERDIR_TILDE - Instead of directories, the returned strings are
737  * tilde-prefixed user names.
738  * COMPLETE_USERDIR_EXACT - Prefix must exactly match a user name.
739  * COMPLETE_USERDIR_ALL - When prefix length is 0, return all user names
740  * instead of the current user only.
741  *
742  * @param[in] prefix Path name to match.
743  * @param len Number of characters to match in "path".
744  * @return List of home directories that match "len" characters of "prefix".
745  */
complete_userdir(const char * prefix,size_t len,int flags)746 static char **complete_userdir(const char *prefix, size_t len, int flags)
747 {
748 	char **ret = NULL;
749 	char *s;
750 	struct passwd *pwd;
751 	size_t n;
752 	size_t i;
753 	int tilde = !!(flags & COMPLETE_USERDIR_TILDE);
754 	int exact = !!(flags & COMPLETE_USERDIR_EXACT);
755 	int all = !!(flags & COMPLETE_USERDIR_ALL);
756 
757 	setpwent();
758 	if ((!all) && (len == 0)) {
759 		if (((pwd = getpwuid(geteuid())) == NULL) ||
760 		    ((ret = calloc(2, sizeof(ret[0]))) == NULL))
761 			goto err;
762 		if (tilde)
763 			s = pwd->pw_name;
764 		else
765 			s = pwd->pw_dir;
766 		i = strlen(s);
767 		if ((ret[0] = calloc((tilde + i + 1),
768 				     sizeof(*ret[0]))) == NULL)
769 			goto err;
770 		if (tilde)
771 			ret[0][0] = '~';
772 		memcpy(&ret[0][tilde], s, i);
773 		ret[0][(tilde + i)] = '\0';
774 		goto end;
775 	}
776 	n = 64;
777 	if ((ret = calloc(n, sizeof(ret[0]))) == NULL)
778 		goto err;
779 	i = 0;
780 	while ((pwd = getpwent()) != NULL) {
781 		size_t j;
782 
783 		if (exact) {
784 			if (strncmp(pwd->pw_name, prefix,
785 				    strlen(pwd->pw_name)))
786 				continue;
787 		}
788 		else if (strncmp(pwd->pw_name, prefix, len))
789 			continue;
790 		if (i == (n - 1)) {
791 			char **tmp;
792 
793 			n += 64;
794 			if ((tmp = realloc(ret, (sizeof(ret[0]) * n))) == NULL)
795 				goto end;
796 			ret = tmp;
797 		}
798 		if (tilde)
799 			s = pwd->pw_name;
800 		else
801 			s = pwd->pw_dir;
802 		j = strlen(s);
803 		if ((ret[i] = calloc((tilde + j + 1),
804 				     sizeof(*ret[0]))) == NULL)
805 			break;
806 		if (tilde)
807 			ret[i][0] = '~';
808 		memcpy(&ret[i][tilde], s, j);
809 		ret[i][(tilde + j)] = '\0';
810 		++i;
811 	}
812 	if (i == 0) {
813 		free(ret);
814 		ret = NULL;
815 	}
816 end:
817 	endpwent();
818 	return ret;
819 err:
820 	endpwent();
821 	free_pppc(&ret, 0);
822 	return NULL;
823 }
824 
825 /**
826  * Return a list of pathnames that match "len" characters of "prefix" on the
827  * file system, or NULL if none was found or if an error occured. This is done
828  * using glob() in order to handle wildcard characters in "prefix".
829  *
830  * When "prefix" isn't explicitly relative nor absolute, if "relative" is
831  * non-NULL, then the path will be completed as if "prefix" was a subdirectory
832  * of "relative". If "relative" is NULL, DGen's home directory will be used.
833  *
834  * If "relative" isn't explicitly relative nor absolute, it will be considered
835  * a subdirectory of DGen's home directory.
836  *
837  * @param[in] prefix Path name to match.
838  * @param len Number of characters to match in "path".
839  * @param[in] relative If non-NULL, consider path relative to this.
840  * @return List of path names that match "len" characters of "prefix".
841  */
complete_path(const char * prefix,size_t len,const char * relative)842 char **complete_path(const char *prefix, size_t len, const char *relative)
843 {
844 	char *s;
845 	char **ret;
846 	size_t i;
847 	glob_t g;
848 	size_t strip;
849 
850 	(void)complete_path_simple; /* unused */
851 	if ((i = strlen(prefix)) < len)
852 		len = i;
853 	else
854 		i = len;
855 	if (((s = strchr(prefix, '/')) != NULL) && ((i = (s - prefix)) > len))
856 		i = len;
857 	if ((len == 0) ||
858 	    ((prefix[0] != '~') &&
859 	     (strncmp(prefix, ".", i)) &&
860 	     (strncmp(prefix, "..", i)))) {
861 		size_t n;
862 
863 		if ((relative == NULL) ||
864 		    (path_type(relative, ~0u) == PATH_TYPE_UNSPECIFIED)) {
865 			char *x = dgen_dir(NULL, &n, relative);
866 
867 			if ((x == NULL) ||
868 			    ((s = realloc(x, (n + 1 + len + 2))) == NULL)) {
869 				free(x);
870 				return NULL;
871 			}
872 		}
873 		else {
874 			n = strlen(relative);
875 			if ((s = malloc(n + 1 + len + 2)) == NULL)
876 				return NULL;
877 			memcpy(s, relative, n);
878 		}
879 		s[(n++)] = '/';
880 		strip = n;
881 		memcpy(&s[n], prefix, len);
882 		len += n;
883 		s[(len++)] = '*';
884 		s[len] = '\0';
885 	}
886 	else if (prefix[0] == '~') {
887 		char **ud;
888 		size_t n;
889 
890 		if (s == NULL)
891 			return complete_userdir(&prefix[1], (i - 1),
892 						(COMPLETE_USERDIR_TILDE |
893 						 COMPLETE_USERDIR_ALL));
894 		ud = complete_userdir(&prefix[1], (i - 1),
895 				      COMPLETE_USERDIR_EXACT);
896 		if (ud == NULL)
897 			goto no_userdir;
898 		n = strlen(ud[0]);
899 		if ((s = realloc(ud[0], (n + (len - i) + 2))) == NULL) {
900 			free_pppc(&ud, 0);
901 			goto no_userdir;
902 		}
903 		free_pppc(&ud, 1);
904 		len -= i;
905 		strip = 0;
906 		memcpy(&s[n], &prefix[i], len);
907 		len += n;
908 		s[(len++)] = '*';
909 		s[len] = '\0';
910 	}
911 	else {
912 	no_userdir:
913 		if ((s = malloc(len + 2)) == NULL)
914 			return NULL;
915 		memcpy(s, prefix, len);
916 		s[(len++)] = '*';
917 		s[len] = '\0';
918 		strip = 0;
919 	}
920 	switch (glob(s, (GLOB_MARK | GLOB_NOESCAPE), NULL, &g)) {
921 	case 0:
922 		break;
923 	case GLOB_NOSPACE:
924 	case GLOB_ABORTED:
925 	case GLOB_NOMATCH:
926 	default:
927 		free(s);
928 		return NULL;
929 	}
930 	free(s);
931 	if ((ret = calloc((g.gl_pathc + 1), sizeof(ret[0]))) == NULL)
932 		goto err;
933 	for (i = 0; (g.gl_pathv[i] != NULL); ++i) {
934 		size_t j;
935 
936 		len = strlen(g.gl_pathv[i]);
937 		if (strip > len)
938 			break;
939 		j = (len - strip);
940 		if ((ret[i] = calloc((j + 1), sizeof(ret[i][0]))) == NULL)
941 			break;
942 		memcpy(ret[i], &(g.gl_pathv[i][strip]), j);
943 		ret[i][j] = '\0';
944 	}
945 	if (i == 0)
946 		goto err;
947 	globfree(&g);
948 	return ret;
949 err:
950 	globfree(&g);
951 	free_pppc(&ret, 0);
952 	return NULL;
953 }
954 
955 #else /* defined(HAVE_GLOB_H) && !defined(__MINGW32__) */
956 
957 /**
958  * Return a list of pathnames that match "len" characters of "prefix" on the
959  * file system, or NULL if none was found or if an error occured.
960  *
961  * When "prefix" isn't explicitly relative nor absolute, if "relative" is
962  * non-NULL, then the path will be completed as if "prefix" was a subdirectory
963  * of "relative". If "relative" is NULL, DGen's home directory will be used.
964  *
965  * If "relative" isn't explicitly relative nor absolute, it will be considered
966  * a subdirectory of DGen's home directory.
967  *
968  * @param[in] prefix Path name to match.
969  * @param len Number of characters to match in "path".
970  * @param[in] relative If non-NULL, consider path relative to this.
971  * @return List of path names that match "len" characters of "prefix".
972  */
complete_path(const char * prefix,size_t len,const char * relative)973 char **complete_path(const char *prefix, size_t len, const char *relative)
974 {
975 	char *s;
976 	char **ret;
977 	size_t i;
978 	size_t n;
979 	size_t strip;
980 	enum path_type pt;
981 
982 	if ((i = strlen(prefix)) < len)
983 		len = i;
984 	if (((pt = path_type(prefix, len)) == PATH_TYPE_ABSOLUTE) ||
985 	    (pt == PATH_TYPE_RELATIVE))
986 		return complete_path_simple(prefix, len);
987 	if ((len != 0) && (prefix[0] == '~') &&
988 	    ((len == 1) ||
989 	     (prefix[1] == '\0') ||
990 	     (strpbrk(prefix, DGEN_DIRSEP) == &prefix[1]))) {
991 		char *x = dgen_userdir(NULL, &n);
992 
993 		if ((x == NULL) ||
994 		    ((s = realloc(x, (n + 1 + 2 + len + 1))) == NULL)) {
995 			free(x);
996 			return NULL;
997 		}
998 		++prefix;
999 		--len;
1000 		strip = 0;
1001 	}
1002 	else if ((relative == NULL) ||
1003 		 (path_type(relative, ~0u) == PATH_TYPE_UNSPECIFIED)) {
1004 		char *x = dgen_dir(NULL, &n, relative);
1005 
1006 		if ((x == NULL) ||
1007 		    ((s = realloc(x, (n + 1 + len + 1))) == NULL)) {
1008 			free(x);
1009 			return NULL;
1010 		}
1011 		strip = (n + 1);
1012 	}
1013 	else {
1014 		n = strlen(relative);
1015 		if ((s = malloc(n + 1 + len + 1)) == NULL)
1016 			return NULL;
1017 		memcpy(s, relative, n);
1018 		strip = (n + 1);
1019 	}
1020 	s[(n++)] = DGEN_DIRSEP[0];
1021 	memcpy(&s[n], prefix, len);
1022 	len += n;
1023 	s[len] = '\0';
1024 	ret = complete_path_simple(s, len);
1025 	free(s);
1026 	if (ret == NULL)
1027 		return NULL;
1028 	if (strip == 0)
1029 		return ret;
1030 	for (i = 0; (ret[i] != NULL); ++i)
1031 		memmove(ret[i], &ret[i][strip],
1032 			((strlen(ret[i]) - strip) + 1));
1033 	return ret;
1034 }
1035 
1036 #endif /* defined(HAVE_GLOB_H) && !defined(__MINGW32__) */
1037 
1038 /**
1039  * Free return value of complete*() functions.
1040  *
1041  * @param[in, out] cp Buffer to pass to free_pppc().
1042  */
complete_path_free(char ** cp)1043 void complete_path_free(char **cp)
1044 {
1045 	free_pppc(&cp, 0);
1046 }
1047 
1048 /**
1049  * Create an escaped version of a string.
1050  * When not NULL, "pos" refers to an offset in string "src". It is updated
1051  * with its new offset value in the escaped string.
1052  *
1053  * @param[in] src String to escape.
1054  * @param size Number of characters from "src" to process.
1055  * @param flags BACKSLASHIFY_* flags.
1056  * @param[in, out] pos Offset in string "src" to update.
1057  * @return Escaped version of "src", NULL on error.
1058  */
backslashify(const uint8_t * src,size_t size,unsigned int flags,size_t * pos)1059 char *backslashify(const uint8_t *src, size_t size, unsigned int flags,
1060 		   size_t *pos)
1061 {
1062 	char *dst = NULL;
1063 	char *tmp;
1064 	size_t i;
1065 	size_t j;
1066 	char buf[5];
1067 
1068 again:
1069 	for (i = 0, j = 0; (i < size); ++i) {
1070 		switch (src[i]) {
1071 		case '\a':
1072 			tmp = "\\a";
1073 			break;
1074 		case '\b':
1075 			tmp = "\\b";
1076 			break;
1077 		case '\f':
1078 			tmp = "\\f";
1079 			break;
1080 		case '\n':
1081 			tmp = "\\n";
1082 			break;
1083 		case '\r':
1084 			tmp = "\\r";
1085 			break;
1086 		case '\t':
1087 			tmp = "\\t";
1088 			break;
1089 		case '\v':
1090 			tmp = "\\v";
1091 			break;
1092 		case '\'':
1093 			if (flags & BACKSLASHIFY_NOQUOTES)
1094 				goto noquotes;
1095 			tmp = "\\'";
1096 			break;
1097 		case '"':
1098 			if (flags & BACKSLASHIFY_NOQUOTES)
1099 				goto noquotes;
1100 			tmp = "\\\"";
1101 			break;
1102 		case ' ':
1103 			if (flags & BACKSLASHIFY_NOQUOTES)
1104 				tmp = " ";
1105 			else
1106 				tmp = "\\ ";
1107 			break;
1108 		case '\0':
1109 			tmp = "\\0";
1110 			break;
1111 		case '\\':
1112 			if (flags & BACKSLASHIFY_NOQUOTES)
1113 				goto noquotes;
1114 			tmp = "\\\\";
1115 			break;
1116 		default:
1117 		noquotes:
1118 			tmp = buf;
1119 			if (isgraph(src[i])) {
1120 				tmp[0] = src[i];
1121 				tmp[1] = '\0';
1122 				break;
1123 			}
1124 			tmp[0] = '\\';
1125 			tmp[1] = 'x';
1126 			snprintf(&tmp[2], 3, "%02x", src[i]);
1127 			break;
1128 		}
1129 		if (dst != NULL)
1130 			strncpy(&dst[j], tmp, strlen(tmp));
1131 		if ((pos != NULL) && (i == *pos)) {
1132 			*pos = j;
1133 			pos = NULL;
1134 		}
1135 		j += strlen(tmp);
1136 	}
1137 	if ((pos != NULL) && (i == *pos)) {
1138 		*pos = j;
1139 		pos = NULL;
1140 	}
1141 	if (dst == NULL) {
1142 		dst = malloc(j + 1);
1143 		if (dst == NULL)
1144 			return NULL;
1145 		dst[j] = '\0';
1146 		goto again;
1147 	}
1148 	return dst;
1149 }
1150 
1151 /**
1152  * Convert a UTF-8 character to its 32 bit representation.
1153  * Return the number of valid bytes for this character.
1154  * On error, u32 is set to (uint32_t)-1.
1155  *
1156  * @param[out] u32 Converted character, (uint32_t)-1 on error.
1157  * @param[in] u8 Multibyte character to convert.
1158  * @return Number of bytes read.
1159  */
utf8u32(uint32_t * u32,const uint8_t * u8)1160 size_t utf8u32(uint32_t *u32, const uint8_t *u8)
1161 {
1162 	static const uint8_t fb[] = {
1163 		/* first byte: mask, expected value, size */
1164 		0x80, 0x00, 1,
1165 		0xe0, 0xc0, 2,
1166 		0xf0, 0xe0, 3,
1167 		0xf8, 0xf0, 4,
1168 		0xfc, 0xf8, 5,
1169 		0xfe, 0xfc, 6,
1170 		0xff, 0x00, 0
1171 	};
1172 	const uint8_t *s = fb;
1173 	size_t i = 0;
1174 	size_t rem;
1175 	uint32_t ret;
1176 
1177 	while ((*u8 & s[0]) != s[1])
1178 		s += 3;
1179 	rem = s[2];
1180 	if (!rem)
1181 		goto error;
1182 	ret = (*u8 & ~s[0]);
1183 	while (++i != rem) {
1184 		++u8;
1185 		if ((*u8 & 0xc0) != 0x80)
1186 			goto error;
1187 		ret <<= 6;
1188 		ret |= (*u8 & ~0xc0);
1189 	}
1190 	if (((ret & ~0x07ff) == 0xd800) ||
1191 	    ((ret & ~0x0001) == 0xfffe))
1192 		goto error;
1193 	*u32 = ret;
1194 	return i;
1195 error:
1196 	*u32 = (uint32_t)-1;
1197 	return i;
1198 }
1199 
1200 /**
1201  * The opposite of utf8u32().
1202  *
1203  * @param[out] u8 Converted character.
1204  * @param u32 Character to convert.
1205  * @return Number of characters written to "u8", 0 on error.
1206  */
utf32u8(uint8_t * u8,uint32_t u32)1207 size_t utf32u8(uint8_t *u8, uint32_t u32)
1208 {
1209 	size_t l;
1210 	size_t i;
1211 	uint8_t fb;
1212 	uint32_t u;
1213 
1214 	if ((u32 & 0x80000000) ||
1215 	    ((u32 & ~0x07ff) == 0xd800) ||
1216 	    ((u32 & ~0x0001) == 0xfffe))
1217 		return 0;
1218 	if (u32 < 0x80) {
1219 		if (u8 != NULL)
1220 			*u8 = u32;
1221 		return 1;
1222 	}
1223 	for (l = 0, u = u32; (u & ~0x3c); ++l)
1224 		u >>= 6;
1225 	if (u8 == NULL)
1226 		return l;
1227 	for (i = l, fb = 0; (--i); u32 >>= 6, fb >>= 1, fb |= 0xc0)
1228 		u8[i] = (0x80 | (u32 & 0x3f));
1229 	u8[0] = (fb | u32);
1230 	return l;
1231 }
1232 
1233 /**
1234  * Look for the longest common prefix between a string and an array
1235  * of strings while ignoring case.
1236  *
1237  * @param[in] str String to compare argv entries to.
1238  * @param[in] argv NULL-terminated array of prefixes to match.
1239  * @return Index in argv or -1 if nothing matches.
1240  */
prefix_casematch(const char * str,const char * argv[])1241 int prefix_casematch(const char *str, const char *argv[])
1242 {
1243 	unsigned int i;
1244 	size_t ret_len = 0;
1245 	int ret = -1;
1246 
1247 	for (i = 0; (argv[i] != NULL); ++i) {
1248 		size_t len = strlen(argv[i]);
1249 
1250 		if ((len < ret_len) ||
1251 		    (strncasecmp(str, argv[i], len)))
1252 			continue;
1253 		ret_len = len;
1254 		ret = i;
1255 	}
1256 	return ret;
1257 }
1258 
1259 /**
1260  * Read number from initial portion of a string and convert it.
1261  *
1262  * @param[in] str String to read from.
1263  * @param[out] num If not NULL, stores the converted number.
1264  * @return Length of the number in str, 0 on error.
1265  */
prefix_getuint(const char * str,unsigned int * num)1266 size_t prefix_getuint(const char *str, unsigned int *num)
1267 {
1268 	size_t len = 0;
1269 	unsigned int ret = 0;
1270 
1271 	while (isdigit(str[len])) {
1272 		ret *= 10;
1273 		ret += (str[len] - '0');
1274 		++len;
1275 	}
1276 	if (len == 0)
1277 		return 0;
1278 	if (num != NULL)
1279 		*num = ret;
1280 	return len;
1281 }
1282