Subversion Repositories Kolibri OS

Rev

Rev 9837 | Rev 9952 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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