1 /*
2  * uadefs decodes Amiga songs transparently into WAV files
3  *
4  * The code was forked from fusexmp example.
5  *
6  * Copyright (C) 2001-2007  Miklos Szeredi <miklos@szeredi.hu>
7  * Copyright (C) 2008       Heikki Orsila <heikki.orsila@iki.fi>
8  *
9  * This program can be distributed under the terms of the GNU GPL.
10  * See the file COPYING.
11  */
12 
13 #define _GNU_SOURCE
14 
15 #define FUSE_USE_VERSION 26
16 
17 #ifdef HAVE_CONFIG_H
18 #include <config.h>
19 #endif
20 
21 #ifdef linux
22 /* For pread()/pwrite() */
23 #define _XOPEN_SOURCE 500
24 #endif
25 
26 #include <pthread.h>
27 #include <fuse.h>
28 #include <stdio.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <dirent.h>
33 #include <errno.h>
34 #include <sys/time.h>
35 #ifdef HAVE_SETXATTR
36 #include <sys/xattr.h>
37 #endif
38 #include <sys/types.h>
39 #include <sys/wait.h>
40 #include <signal.h>
41 #include <string.h>
42 #include <strings.h>
43 #include <stdlib.h>
44 #include <stdio.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 #include <assert.h>
48 #include <time.h>
49 
50 #include "uadeconf.h"
51 #include "uadestate.h"
52 #include "eagleplayer.h"
53 #include "songdb.h"
54 #include "uadeconfig.h"
55 #include "ossupport.h"
56 
57 
58 #define WAV_HEADER_LEN 44
59 
60 #define CACHE_BLOCK_SHIFT 12  /* 4096 bytes per cache block */
61 #define CACHE_BLOCK_SIZE (1 << CACHE_BLOCK_SHIFT)
62 #define CACHE_LSB_MASK (CACHE_BLOCK_SIZE - 1)
63 #define CACHE_SECONDS 512
64 #define SND_PER_SECOND (44100 * 4)
65 
66 #define NSTASHES 4
67 #define STASH_CACHE_BLOCKS 2
68 #define STASH_SIZE (CACHE_BLOCK_SIZE * STASH_CACHE_BLOCKS)
69 #define STASH_TIME 30
70 
71 #define DEBUG(fmt, args...) if (debugmode) { fprintf(stderr, fmt, ## args); }
72 
73 #define LOG(fmt, args...) if (debugfd != -1) { \
74         char debugmsg[4096]; \
75         int debuglen; \
76         DEBUG(fmt, ## args); \
77         debuglen = snprintf(debugmsg, sizeof debugmsg, fmt, ## args); \
78         xwrite(debugfd, debugmsg, debuglen); \
79     }
80 
81 #define DIE(fmt, args...) do {fprintf(stderr, fmt, ## args); exit(1); } while (0)
82 
83 #define LOGDIE(fmt, args...) do {LOG(fmt, ## args); abort();} while (0)
84 
85 #define MAX(x, y) (x >= y) ? (x) : (y)
86 #define MIN(x, y) (x <= y) ? (x) : (y)
87 
88 
89 struct cacheblock {
90 	unsigned int bytes; /* 0 <= bytes <= CACHE_BLOCK_SIZE */
91 	void *data;
92 };
93 
94 struct sndctx {
95 	int normalfile;       /* if non-zero, the file is not decoded */
96 	int pipefd;           /* pipefd from which to read sound data */
97 	pid_t pid;            /* pid of the decoding process */
98 	char fname[PATH_MAX]; /* filename of the song being played */
99 
100 	size_t nblocks;
101 	size_t end_bi;
102 	struct cacheblock *blocks;
103 };
104 
105 struct stash {
106 	/* Add time invalidation */
107 	char fname[PATH_MAX];          /* File name for the stash */
108 	char data[STASH_SIZE];
109 	time_t created;               /* Timestamp for validity checks */
110 };
111 
112 
113 static char *srcdir = NULL;
114 static int debugfd = -1;
115 static int debugmode;
116 static struct uade_state uadestate;
117 static time_t mtime = 0;
118 static pthread_mutex_t readmutex = PTHREAD_MUTEX_INITIALIZER;
119 
120 int nextstash;
121 struct stash stashes[NSTASHES];
122 
123 
124 static ssize_t get_file_size(const char *path);
125 
126 /*
127  * xread() is the same as the read(), but it automatically restarts read()
128  * operations with a recoverable error (EAGAIN and EINTR). xread()
129  * DOES NOT GUARANTEE that "len" bytes is read even if the data is available.
130  */
xread(int fd,void * buf,size_t count)131 static ssize_t xread(int fd, void *buf, size_t count)
132 {
133 	ssize_t nr;
134 	while (1) {
135 		nr = read(fd, buf, count);
136 		if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
137 			continue;
138 		return nr;
139 	}
140 }
141 
xwrite(int fd,const void * buf,size_t count)142 static ssize_t xwrite(int fd, const void *buf, size_t count)
143 {
144 	ssize_t nr;
145 	while (1) {
146 		nr = write(fd, buf, count);
147 		if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
148 			continue;
149 		return nr;
150 	}
151 }
152 
read_in_full(int fd,void * buf,size_t count)153 ssize_t read_in_full(int fd, void *buf, size_t count)
154 {
155 	char *p = buf;
156 	ssize_t total = 0;
157 
158 	while (count > 0) {
159 		ssize_t loaded = xread(fd, p, count);
160 		if (loaded <= 0)
161 			return total ? total : loaded;
162 		count -= loaded;
163 		p += loaded;
164 		total += loaded;
165 	}
166 
167 	return total;
168 }
169 
uadefs_get_path(int * isuade,const char * path)170 static char *uadefs_get_path(int *isuade, const char *path)
171 {
172 	char *realpath;
173 	char *sep;
174 	struct stat st;
175 
176 	if (isuade)
177 		*isuade = 0;
178 
179 	if (asprintf(&realpath, "%s%s", srcdir, path) < 0)
180 		LOGDIE("No memory for path name: %s\n", path);
181 
182 	if (!lstat(realpath, &st))
183 		goto out;
184 
185 	/* File doesn't exist */
186 	sep = strrchr(realpath, '.');
187 	if (sep == NULL || strcmp(sep, ".wav") != 0)
188 		goto out;
189 
190 	*sep = 0;
191 
192 	if (uade_is_our_file(realpath, 1, &uadestate)) {
193 		if (isuade)
194 			*isuade = 1;
195 	} else {
196 		/* Not an UADE file -> restore .wav postfix */
197 		*sep = '.';
198 	}
199 out:
200 	return realpath;
201 }
202 
spawn_uade(struct sndctx * ctx)203 static int spawn_uade(struct sndctx *ctx)
204 {
205 	int fds[2];
206 
207 	LOG("Spawn UADE %s\n", ctx->fname);
208 
209 	if (pipe(fds)) {
210 		LOG("Can not create a pipe\n");
211 		return -errno;
212 	}
213 
214 	ctx->pid = fork();
215 	if (ctx->pid == 0) {
216 		char *argv[] = {"uade123", "-c", "-k0", "--stderr", "-v",
217 				ctx->fname, NULL};
218 		int fd;
219 
220 		close(0);
221 		close(2);
222 		close(fds[0]);
223 
224 		fd = open("/dev/null", O_RDWR);
225 		if (fd < 0)
226 			LOGDIE("Can not open /dev/null\n");
227 
228 		dup2(fd, 0);
229 		dup2(fds[1], 1);
230 		dup2(fd, 2);
231 
232 		DEBUG("Execute %s\n", UADENAME);
233 
234 		execv(UADENAME, argv);
235 
236 		LOGDIE("Could not execute %s\n", UADENAME);
237 	} else if (ctx->pid == -1) {
238 		LOG("Can not fork\n");
239 		close(fds[0]);
240 		close(fds[1]);
241 		return -errno;
242 	}
243 
244 	ctx->pipefd = fds[0];
245 	close(fds[1]);
246 
247 	return 0;
248 }
249 
cache_block_read(struct sndctx * ctx,char * buf,size_t offset,size_t size)250 static ssize_t cache_block_read(struct sndctx *ctx, char *buf, size_t offset,
251 				size_t size)
252 {
253 	size_t toread;
254 	size_t offset_bi;
255 	size_t lsb;
256 	struct cacheblock *cb;
257 
258 	offset_bi = offset >> CACHE_BLOCK_SHIFT;
259 
260 	if (offset_bi >= ctx->nblocks) {
261 		LOG("Too much sound data: %zu >= %zu: %s\n", offset_bi, ctx->nblocks, ctx->fname);
262 		return 0;
263 	}
264 
265 	cb = &ctx->blocks[offset_bi];
266 
267 	if (!cb->bytes)
268 		return -1;
269 
270 	lsb = offset & CACHE_LSB_MASK;
271 
272 	if ((lsb + size) > CACHE_BLOCK_SIZE)
273 		LOGDIE("lsb + size (%zd) failed: %zd %zd\n", lsb + size, offset, size);
274 
275 	if (lsb >= cb->bytes)
276 		return 0;
277 
278 	toread = MIN(size, cb->bytes - lsb);
279 
280 	memcpy(buf, ((char *) cb->data) + lsb, toread);
281 
282 	return toread;
283 }
284 
cache_init(struct sndctx * ctx)285 static void cache_init(struct sndctx *ctx)
286 {
287 	ctx->end_bi = 0;
288 	ctx->nblocks = (SND_PER_SECOND * CACHE_SECONDS + CACHE_BLOCK_SIZE - 1) >> CACHE_BLOCK_SHIFT;
289 	ctx->blocks = calloc(1, ctx->nblocks * sizeof(ctx->blocks[0]));
290 	if (ctx->blocks == NULL)
291 		LOGDIE("No memory for cache\n");
292 }
293 
cache_read(struct sndctx * ctx,char * buf,size_t offset,size_t size)294 static size_t cache_read(struct sndctx *ctx, char *buf, size_t offset,
295 			 size_t size)
296 {
297 	size_t offset_bi;
298 	struct cacheblock *cb;
299 	ssize_t res;
300 
301 	offset_bi = offset >> CACHE_BLOCK_SHIFT;
302 
303 	if (offset_bi >= STASH_CACHE_BLOCKS && ctx->pid == -1) {
304 		char buf[CACHE_BLOCK_SIZE];
305 		int i;
306 
307 		if (spawn_uade(ctx))
308 			return 0;
309 
310 		for (i = 0; i < STASH_CACHE_BLOCKS; i++) {
311 			res = read_in_full(ctx->pipefd, buf, sizeof buf);
312 			if (res < sizeof buf)
313 				return 0;
314 		}
315 	}
316 
317 	/* The requested block is already in cache, copy it directly */
318 	res = cache_block_read(ctx, buf, offset, size);
319 	if (res >= 0)
320 		return (size_t) res;
321 
322 	if (offset_bi >= ctx->nblocks) {
323 		LOG("Too much sound data: %s\n", ctx->fname);
324 		return 0;
325 	}
326 
327 	/*
328 	 * Read cache blocks in sequence until the requested cache block
329 	 * has been read. ctx->end_bi is increased every time a new block
330 	 * is read. ctx->end_bi points to the first block that is not cached.
331 	 */
332 	while (ctx->end_bi <= offset_bi) {
333 		cb = &ctx->blocks[ctx->end_bi];
334 
335 		cb->data = malloc(CACHE_BLOCK_SIZE);
336 		if (cb->data == NULL) {
337 			LOG("Out of memory: %s\n", ctx->fname);
338 			break;
339 		}
340 
341 		res = read_in_full(ctx->pipefd, cb->data, CACHE_BLOCK_SIZE);
342 		if (res <= 0) {
343 			free(cb->data);
344 			cb->data = NULL;
345 			DEBUG("Read code %d at %zd: %s\n", (int) res, ctx->end_bi << CACHE_BLOCK_SHIFT, ctx->fname);
346 			break;
347 		}
348 
349 		cb->bytes = res;
350 
351 		ctx->end_bi++;
352 
353 		if (res < CACHE_BLOCK_SIZE)
354 			break;
355 	}
356 
357 	res = cache_block_read(ctx, buf, offset, size);
358 	if (res >= 0)
359 		return (size_t) res;
360 
361 	return 0;
362 }
363 
cache_prefill(struct sndctx * ctx,char * data)364 int cache_prefill(struct sndctx *ctx, char *data)
365 {
366 	int i;
367 
368 	if (data == NULL)
369 		LOGDIE("Prefill segfault: %s\n", ctx->fname);
370 
371 	ctx->end_bi = STASH_CACHE_BLOCKS;
372 
373 	for (i = 0; i < STASH_CACHE_BLOCKS; i++) {
374 		ctx->blocks[i].data = malloc(CACHE_BLOCK_SIZE);
375 		if (ctx->blocks[i].data == NULL) {
376 			LOG("Prefill OOM: %s\n", ctx->fname);
377 			break;
378 		}
379 		ctx->blocks[i].bytes = CACHE_BLOCK_SIZE;
380 		memcpy(ctx->blocks[i].data, data, CACHE_BLOCK_SIZE);
381 		data += CACHE_BLOCK_SIZE;
382 	}
383 
384 	if (i < STASH_CACHE_BLOCKS) {
385 		/* Free cache blocks from the beginning to the first NULL */
386 		for (i = 0; i < STASH_CACHE_BLOCKS; i++) {
387 			if (ctx->blocks[i].data == NULL)
388 				break;
389 			free(ctx->blocks[i].data);
390 			ctx->blocks[i].data = NULL;
391 		}
392 		return -1;
393 	}
394 
395 	return 0;
396 }
397 
write_le_32(char * data,int32_t v)398 static void write_le_32(char *data, int32_t v)
399 {
400 	data[0] = v         & 0xff;
401 	data[1] = (v >> 8)  & 0xff;
402 	data[2] = (v >> 16) & 0xff;
403 	data[3] = (v >> 24) & 0xff;
404 }
405 
cache_invasive_write(struct sndctx * ctx,size_t offset,char * data,size_t len)406 static void cache_invasive_write(struct sndctx *ctx, size_t offset,
407 				 char *data, size_t len)
408 {
409 	size_t offset_bi = offset >> CACHE_BLOCK_SHIFT;
410 	size_t lsbpos = offset & CACHE_LSB_MASK;
411 	struct cacheblock *cb;
412 
413 	if (offset_bi >= ctx->end_bi) {
414 		LOG("Invasive cache write: %zu\n", offset);
415 		return;
416 	}
417 
418 	cb = &ctx->blocks[offset_bi];
419 
420 	if ((lsbpos + len) <= cb->bytes)
421 		memcpy(((char *) cb->data) + lsbpos, data, len);
422 }
423 
create_ctx(const char * path)424 static struct sndctx *create_ctx(const char *path)
425 {
426 	struct sndctx *ctx;
427 
428 	ctx = calloc(1, sizeof ctx[0]);
429 	if (ctx == NULL)
430 		return NULL;
431 
432 	strlcpy(ctx->fname, path, sizeof ctx->fname);
433 
434 	ctx->pipefd = -1;
435 	ctx->pid = -1;
436 
437 	return ctx;
438 }
439 
destroy_cache(struct sndctx * ctx)440 static void destroy_cache(struct sndctx *ctx)
441 {
442 	size_t cbi;
443 
444 	if (ctx->blocks != NULL) {
445 		for (cbi = 0; cbi < ctx->nblocks; cbi++) {
446 			ctx->blocks[cbi].bytes = 0;
447 			free(ctx->blocks[cbi].data);
448 			ctx->blocks[cbi].data = NULL;
449 		}
450 
451 		free(ctx->blocks);
452 		ctx->blocks = NULL;
453 		ctx->end_bi = 0;
454 		ctx->nblocks = 0;
455 	}
456 }
457 
kill_child(struct sndctx * ctx)458 static void kill_child(struct sndctx *ctx)
459 {
460 	if (ctx->pid != -1) {
461 		kill(ctx->pid, SIGINT);
462 		while (waitpid(ctx->pid, NULL, 0) <= 0);
463 		ctx->pid = -1;
464 	}
465 }
466 
set_no_snd_file(struct sndctx * ctx)467 static void set_no_snd_file(struct sndctx *ctx)
468 {
469 	ctx->normalfile = 1;
470 
471 	destroy_cache(ctx);
472 
473 	kill_child(ctx);
474 
475 	close(ctx->pipefd);
476 	ctx->pipefd = -1;
477 }
478 
destroy_ctx(struct sndctx * ctx)479 static void destroy_ctx(struct sndctx *ctx)
480 {
481 	ctx->fname[0] = 0;
482 
483 	if (ctx->normalfile == 0)
484 		set_no_snd_file(ctx);
485 
486 	free(ctx);
487 }
488 
get_uadefs_file(struct fuse_file_info * fi)489 static inline struct sndctx *get_uadefs_file(struct fuse_file_info *fi)
490 {
491 	return (struct sndctx *) (uintptr_t) fi->fh;
492 }
493 
check_stash(const char * fname,struct stash * stash,time_t t)494 static int check_stash(const char *fname, struct stash *stash, time_t t)
495 {
496 	if (strcmp(fname, stash->fname) != 0)
497 		return 0;
498 
499 	/* Reject old stashes */
500 	if (t >= (stash->created + STASH_TIME))
501 		return 0;
502 
503 	return 1;
504 }
505 
warm_up_cache(struct sndctx * ctx)506 int warm_up_cache(struct sndctx *ctx)
507 {
508 	char crapbuf[STASH_SIZE];
509 	ssize_t s;
510 	int i;
511 	struct stash *stash;
512 	size_t offs;
513 	time_t created;
514 
515 	created = time(NULL);
516 	if (created == ((time_t) -1)) {
517 		LOG("Clock failed\n");
518 		created = 0;
519 	}
520 
521 	for (i = 0; i < NSTASHES; i++) {
522 		if (check_stash(ctx->fname, &stashes[i], created)) {
523 			LOG("Found stash for %s\n", ctx->fname);
524 			if (cache_prefill(ctx, stashes[i].data))
525 				return -EIO;
526 			break;
527 		}
528 	}
529 
530 	/* Start uade iff no stash found */
531 	if (i == NSTASHES) {
532 		int ret = spawn_uade(ctx);
533 		if (ret)
534 			return ret;
535 	}
536 
537 	for (offs = 0; offs < sizeof crapbuf; offs += CACHE_BLOCK_SIZE) {
538 		if (cache_read(ctx, &crapbuf[offs], offs, CACHE_BLOCK_SIZE) < CACHE_BLOCK_SIZE) {
539 			DEBUG("File is not playable: %s\n", ctx->fname);
540 			set_no_snd_file(ctx);
541 			return -EIO;
542 		}
543 	}
544 
545 	s = get_file_size(ctx->fname);
546 	if (s > 0 &&
547 	    memcmp(&crapbuf[0], "RIFF", 4) == 0 &&
548 	    memcmp(&crapbuf[8], "WAVE", 4) == 0    ) {
549 		/* Fix WAV header */
550 		char data[4];
551 
552 		write_le_32(data, (int32_t) (s - 8));
553 		cache_invasive_write(ctx, 4, data, 4);
554 
555 		write_le_32(data, (int32_t) (s - 44));
556 		cache_invasive_write(ctx, 40, data, 4);
557 	}
558 
559 	if (i == NSTASHES) {
560 		/* We found no stash -> create one from crapbuf */
561 		stash = &stashes[nextstash++];
562 		if (nextstash >= NSTASHES)
563 			nextstash = 0;
564 
565 		if (sizeof(stash->data) != sizeof(crapbuf))
566 			LOGDIE("Stash data != crapbuf\n");
567 
568 		stash->created = created;
569 		strlcpy(stash->fname, ctx->fname, sizeof stash->fname);
570 		memcpy(stash->data, crapbuf, sizeof stash->data);
571 
572 		LOG("Allocated stash for %s\n", ctx->fname);
573 	}
574 
575 	return 0;
576 }
577 
open_file(int * success,const char * path,int isuade)578 static struct sndctx *open_file(int *success, const char *path, int isuade)
579 {
580 	int ret;
581 	struct sndctx *ctx;
582 	struct stat st;
583 
584 	ctx = create_ctx(path);
585 	if (ctx == NULL) {
586 		ret = -ENOMEM;
587 		goto err;
588 	}
589 
590 	if (stat(path, &st)) {
591 		ret = -errno;
592 		goto err;
593 	}
594 
595 	if (!S_ISREG(st.st_mode) || !isuade) {
596 		set_no_snd_file(ctx);
597 		goto out;
598 	}
599 
600 	cache_init(ctx);
601 
602 	ret = warm_up_cache(ctx);
603 	if (ret < 0)
604 		goto err;
605  out:
606 	*success = 0;
607 	return ctx;
608 
609  err:
610 	if (ctx)
611 		destroy_ctx(ctx);
612 
613 	*success = ret;
614 	return NULL;
615 }
616 
load_content_db(void)617 static void load_content_db(void)
618 {
619 	struct stat st;
620 	char name[PATH_MAX] = "";
621 	char *home;
622 	int ret;
623 
624 	home = getenv("HOME");
625 	if (home)
626 		snprintf(name, sizeof name, "%s/.uade2/contentdb", home);
627 
628 	/* User database has priority over global database, so we read it
629 	 * first */
630 	if (name[0]) {
631 		if (stat(name, &st) == 0) {
632 			if (mtime < st.st_mtime) {
633 				ret = uade_read_content_db(name);
634 				if (stat(name, &st) == 0)
635 					mtime = st.st_mtime;
636 				if (ret)
637 					return;
638 			}
639 		} else {
640 			FILE *f = fopen(name, "w");
641 			if (f)
642 				fclose(f);
643 			uade_read_content_db(name);
644 		}
645 	}
646 
647 	snprintf(name, sizeof name, "%s/contentdb.conf", uadestate.config.basedir.name);
648 	if (stat(name, &st) == 0 && mtime < st.st_mtime) {
649 		uade_read_content_db(name);
650 		if (stat(name, &st) == 0)
651 			mtime = st.st_mtime;
652 	}
653 }
654 
655 /*
656  * If the file is an uade song, return a heuristic wav file size, a positive
657  * integer. Otherwise, return zero.
658  */
get_file_size(const char * path)659 static ssize_t get_file_size(const char *path)
660 {
661 	int64_t msecs;
662 
663 	if (!uade_is_our_file(path, 1, &uadestate))
664 		return 0;
665 
666 	/*
667 	 * HACK HACK. Use playlength stored in the content database
668 	 * or lie about the time.
669 	 */
670 	load_content_db();
671 	if (!uade_alloc_song(&uadestate, path))
672 		return -1;
673 
674 	msecs = uadestate.song->playtime;
675 	uade_unalloc_song(&uadestate);
676 
677 	if (msecs > 3600000)
678 		return -1;
679 
680 	if (msecs <= 0)
681 		msecs = 1000 * CACHE_SECONDS;
682 
683 	return WAV_HEADER_LEN + (((msecs * SND_PER_SECOND) / 1000) & ~0x3);
684 }
685 
uadefs_getattr(const char * fpath,struct stat * stbuf)686 static int uadefs_getattr(const char *fpath, struct stat *stbuf)
687 {
688 	int res;
689 	char *path = uadefs_get_path(NULL, fpath);
690 	ssize_t s;
691 
692 	res = lstat(path, stbuf);
693 	if (res == -1) {
694 		free(path);
695 		return -errno;
696 	}
697 
698 	s = get_file_size(path);
699 
700 	free(path);
701 	path = NULL;
702 
703 	if (s > 0) {
704 		stbuf->st_size = s; /* replace the lstat() value */
705 		stbuf->st_blocks = stbuf->st_size / 512;
706 	} else if (s < 0) {
707 		return -ENOMEM;
708 	}
709 	/* For s == 0, the result of lstat() is returned */
710 	return 0;
711 }
712 
uadefs_access(const char * fpath,int mask)713 static int uadefs_access(const char *fpath, int mask)
714 {
715 	int res;
716 	char *path = uadefs_get_path(NULL, fpath);
717 
718 	res = access(path, mask);
719 
720 	free(path);
721 
722 	if (res == -1)
723 		return -errno;
724 
725 	return 0;
726 }
727 
uadefs_readlink(const char * fpath,char * buf,size_t size)728 static int uadefs_readlink(const char *fpath, char *buf, size_t size)
729 {
730 	int res;
731 	char *path = uadefs_get_path(NULL, fpath);
732 
733 	res = readlink(path, buf, size - 1);
734 
735 	free(path);
736 
737 	if (res == -1)
738 		return -errno;
739 
740 	buf[res] = '\0';
741 	return 0;
742 }
743 
744 
gen_uade_name(char * name,size_t maxname,mode_t mode,const char * dirname,const char * filename)745 static void gen_uade_name(char *name, size_t maxname, mode_t mode,
746 			  const char *dirname, const char *filename)
747 {
748 	char fullname[PATH_MAX];
749 
750 	snprintf(name, maxname, "%s", filename);
751 
752 	if (!S_ISREG(mode))
753 		return;
754 
755 	snprintf(fullname, sizeof fullname, "%s/%s", dirname, filename);
756 
757 	if (!uade_is_our_file(fullname, 1, &uadestate))
758 		return;
759 
760 	snprintf(name, maxname, "%s.wav", filename);
761 }
762 
763 
uadefs_readdir(const char * fpath,void * buf,fuse_fill_dir_t filler,off_t offset,struct fuse_file_info * fi)764 static int uadefs_readdir(const char *fpath, void *buf, fuse_fill_dir_t filler,
765 			  off_t offset, struct fuse_file_info *fi)
766 {
767 	DIR *dp;
768 	struct dirent *de;
769 	char *path = uadefs_get_path(NULL, fpath);
770 	char name[256];
771 	char fullname[PATH_MAX];
772 
773 	(void) offset;
774 	(void) fi;
775 
776 	dp = opendir(path);
777 
778 	if (dp == NULL) {
779 		free(path);
780 		return -errno;
781 	}
782 
783 	while ((de = readdir(dp)) != NULL) {
784 		struct stat st;
785 		memset(&st, 0, sizeof(st));
786 		st.st_ino = de->d_ino;
787 		st.st_mode = de->d_type << 12;
788 		if (st.st_mode == 0) {
789 			/* de->d_type not supported -> use stat() */
790 			struct stat oldst;
791 			snprintf(fullname, sizeof fullname, "%s/%s", path, de->d_name);
792 			if (!stat(fullname, &oldst))
793 				st.st_mode = oldst.st_mode & ~0777;
794 		}
795 
796 		gen_uade_name(name, sizeof name, st.st_mode, path, de->d_name);
797 
798 		if (filler(buf, name, &st, 0))
799 			break;
800 	}
801 
802 	free(path);
803 	closedir(dp);
804 	return 0;
805 }
806 
uadefs_mknod(const char * fpath,mode_t mode,dev_t rdev)807 static int uadefs_mknod(const char *fpath, mode_t mode, dev_t rdev)
808 {
809 	(void) mode;
810 	(void) fpath;
811 	(void) rdev;
812 	return -EACCES;
813 }
814 
uadefs_mkdir(const char * fpath,mode_t mode)815 static int uadefs_mkdir(const char *fpath, mode_t mode)
816 {
817 	int res;
818 	char *path = uadefs_get_path(NULL, fpath);
819 
820 	res = mkdir(path, mode);
821 
822 	free(path);
823 
824 	if (res == -1)
825 		return -errno;
826 
827 	return 0;
828 }
829 
uadefs_unlink(const char * fpath)830 static int uadefs_unlink(const char *fpath)
831 {
832 	int res;
833 	char *path = uadefs_get_path(NULL, fpath);
834 
835 	res = unlink(path);
836 
837 	free(path);
838 
839 	if (res == -1)
840 		return -errno;
841 
842 	return 0;
843 }
844 
uadefs_rmdir(const char * fpath)845 static int uadefs_rmdir(const char *fpath)
846 {
847 	int res;
848 	char *path = uadefs_get_path(NULL, fpath);
849 
850 	res = rmdir(path);
851 
852 	free(path);
853 
854 	if (res == -1)
855 		return -errno;
856 
857 	return 0;
858 }
859 
uadefs_symlink(const char * ffrom,const char * fto)860 static int uadefs_symlink(const char *ffrom, const char *fto)
861 {
862 	int res;
863 	char *from = uadefs_get_path(NULL, ffrom);
864 	char *to = uadefs_get_path(NULL, fto);
865 
866 	res = symlink(from, to);
867 
868 	free(from);
869 	free(to);
870 
871 	if (res == -1)
872 		return -errno;
873 
874 	return 0;
875 }
876 
uadefs_rename(const char * ffrom,const char * fto)877 static int uadefs_rename(const char *ffrom, const char *fto)
878 {
879 	int res;
880 	char *from = uadefs_get_path(NULL, ffrom);
881 	char *to = uadefs_get_path(NULL, fto);
882 
883 	res = rename(from, to);
884 
885 	free(from);
886 	free(to);
887 
888 	if (res == -1)
889 		return -errno;
890 
891 	return 0;
892 }
893 
uadefs_link(const char * ffrom,const char * fto)894 static int uadefs_link(const char *ffrom, const char *fto)
895 {
896 	int res;
897 	char *from = uadefs_get_path(NULL, ffrom);
898 	char *to = uadefs_get_path(NULL, fto);
899 
900 	res = link(from, to);
901 
902 	free(from);
903 	free(to);
904 
905 	if (res == -1)
906 		return -errno;
907 
908 	return 0;
909 }
910 
uadefs_chmod(const char * fpath,mode_t mode)911 static int uadefs_chmod(const char *fpath, mode_t mode)
912 {
913 	int res;
914 	char *path = uadefs_get_path(NULL, fpath);
915 
916 	res = chmod(path, mode);
917 
918 	free(path);
919 
920 	if (res == -1)
921 		return -errno;
922 
923 	return 0;
924 }
925 
uadefs_chown(const char * fpath,uid_t uid,gid_t gid)926 static int uadefs_chown(const char *fpath, uid_t uid, gid_t gid)
927 {
928 	int res;
929 	char *path = uadefs_get_path(NULL, fpath);
930 
931 	res = lchown(path, uid, gid);
932 
933 	free(path);
934 
935 	if (res == -1)
936 		return -errno;
937 
938 	return 0;
939 }
940 
uadefs_truncate(const char * fpath,off_t size)941 static int uadefs_truncate(const char *fpath, off_t size)
942 {
943 	(void) fpath;
944 	(void) size;
945 
946 	return -EIO;
947 }
948 
uadefs_utimens(const char * fpath,const struct timespec ts[2])949 static int uadefs_utimens(const char *fpath, const struct timespec ts[2])
950 {
951 	int res;
952 	struct timeval tv[2];
953 	char *path = uadefs_get_path(NULL, fpath);
954 
955 	tv[0].tv_sec = ts[0].tv_sec;
956 	tv[0].tv_usec = ts[0].tv_nsec / 1000;
957 	tv[1].tv_sec = ts[1].tv_sec;
958 	tv[1].tv_usec = ts[1].tv_nsec / 1000;
959 
960 	res = utimes(path, tv);
961 
962 	free(path);
963 
964 	if (res == -1)
965 		return -errno;
966 
967 	return 0;
968 }
969 
uadefs_open(const char * fpath,struct fuse_file_info * fi)970 static int uadefs_open(const char *fpath, struct fuse_file_info *fi)
971 {
972 	int ret;
973 	struct sndctx *ctx;
974 	int isuade;
975 	char *path = uadefs_get_path(&isuade, fpath);
976 
977 	if (fi->flags & O_CREAT) {
978 		free(path);
979 		return -EPERM;
980 	}
981 
982 	ctx = open_file(&ret, path, isuade);
983 
984 	free(path);
985 
986 	if (ctx == NULL)
987 		return ret;
988 
989 	fi->direct_io = 1;
990 	fi->fh = (uint64_t) (uintptr_t) ctx;
991 
992 	DEBUG("Opened %s as %s file\n", ctx->fname, ctx->normalfile ? "normal" : "UADE");
993 	return 0;
994 }
995 
uadefs_read(const char * fpath,char * buf,size_t size,off_t off,struct fuse_file_info * fi)996 static int uadefs_read(const char *fpath, char *buf, size_t size, off_t off,
997 		       struct fuse_file_info *fi)
998 {
999 	int fd;
1000 	size_t res;
1001 	struct sndctx *ctx = get_uadefs_file(fi);
1002 	ssize_t totalread = 0;
1003 	size_t bsize;
1004 
1005 	if (ctx->normalfile) {
1006 		char *path = uadefs_get_path(NULL, fpath);
1007 
1008 		fd = open(path, O_RDONLY);
1009 
1010 		free(path);
1011 
1012 		if (fd == -1)
1013 			return -errno;
1014 
1015 		totalread = pread(fd, buf, size, off);
1016 		if (totalread == -1)
1017 			totalread = -errno;
1018 
1019 		close(fd);
1020 
1021 		return totalread;
1022 	}
1023 
1024 	pthread_mutex_lock(&readmutex);
1025 
1026 	while (size > 0) {
1027 		bsize = MIN(CACHE_BLOCK_SIZE - (off & CACHE_LSB_MASK), size);
1028 		res = cache_read(ctx, buf, off, bsize);
1029 		if (res == 0)
1030 			break;
1031 
1032 		totalread += res;
1033 		buf += res;
1034 		off += res;
1035 		size -= res;
1036 	}
1037 
1038 	DEBUG("read() returns %zd\n", totalread);
1039 	pthread_mutex_unlock(&readmutex);
1040 
1041 	return totalread;
1042 }
1043 
uadefs_write(const char * fpath,const char * buf,size_t size,off_t offset,struct fuse_file_info * fi)1044 static int uadefs_write(const char *fpath, const char *buf, size_t size,
1045 			off_t offset, struct fuse_file_info *fi)
1046 {
1047 	(void) fpath;
1048 	(void) buf;
1049 	(void) size;
1050 	(void) offset;
1051 	(void) fi;
1052 
1053 	return -EIO;
1054 }
1055 
uadefs_statfs(const char * fpath,struct statvfs * stbuf)1056 static int uadefs_statfs(const char *fpath, struct statvfs *stbuf)
1057 {
1058 	int res;
1059 	char *path = uadefs_get_path(NULL, fpath);
1060 
1061 	res = statvfs(path, stbuf);
1062 
1063 	free(path);
1064 
1065 	if (res == -1)
1066 		return -errno;
1067 
1068 	return 0;
1069 }
1070 
uadefs_flush(const char * fpath,struct fuse_file_info * fi)1071 static int uadefs_flush(const char *fpath, struct fuse_file_info *fi)
1072 {
1073 	(void) fi;
1074 	(void) fpath;
1075 	return 0;
1076 }
1077 
uadefs_release(const char * fpath,struct fuse_file_info * fi)1078 static int uadefs_release(const char *fpath, struct fuse_file_info *fi)
1079 {
1080 	destroy_ctx(get_uadefs_file(fi));
1081 
1082 	DEBUG("release %s\n", fpath);
1083 
1084 	return 0;
1085 }
1086 
uadefs_fsync(const char * fpath,int isdatasync,struct fuse_file_info * fi)1087 static int uadefs_fsync(const char *fpath, int isdatasync,
1088 		     struct fuse_file_info *fi)
1089 {
1090 	/* Just a stub.	 This method is optional and can safely be left
1091 	   unimplemented */
1092 
1093 	(void) fpath;
1094 	(void) isdatasync;
1095 	(void) fi;
1096 	return 0;
1097 }
1098 
1099 #ifdef HAVE_SETXATTR
1100 /* xattr operations are optional and can safely be left unimplemented */
uadefs_setxattr(const char * fpath,const char * name,const char * value,size_t size,int flags)1101 static int uadefs_setxattr(const char *fpath, const char *name, const char *value,
1102 			size_t size, int flags)
1103 {
1104 	char *path = uadefs_get_path(NULL, fpath);
1105 	int res;
1106 
1107 	res = lsetxattr(path, name, value, size, flags);
1108 
1109 	free(path);
1110 
1111 	if (res == -1)
1112 		return -errno;
1113 	return 0;
1114 }
1115 
uadefs_getxattr(const char * fpath,const char * name,char * value,size_t size)1116 static int uadefs_getxattr(const char *fpath, const char *name, char *value,
1117 			size_t size)
1118 {
1119 	char *path = uadefs_get_path(NULL, fpath);
1120 	int res;
1121 
1122 	res = lgetxattr(path, name, value, size);
1123 
1124 	free(path);
1125 
1126 	if (res == -1)
1127 		return -errno;
1128 	return res;
1129 }
1130 
uadefs_listxattr(const char * fpath,char * list,size_t size)1131 static int uadefs_listxattr(const char *fpath, char *list, size_t size)
1132 {
1133 	char *path = uadefs_get_path(NULL, fpath);
1134 	int res;
1135 
1136 	res = llistxattr(path, list, size);
1137 
1138 	free(path);
1139 
1140 	if (res == -1)
1141 		return -errno;
1142 	return res;
1143 }
1144 
uadefs_removexattr(const char * fpath,const char * name)1145 static int uadefs_removexattr(const char *fpath, const char *name)
1146 {
1147 	char *path = uadefs_get_path(NULL, fpath);
1148 	int res;
1149 
1150 	res = lremovexattr(path, name);
1151 
1152 	free(path);
1153 
1154 	if (res == -1)
1155 		return -errno;
1156 	return 0;
1157 }
1158 #endif /* HAVE_SETXATTR */
1159 
1160 static struct fuse_operations uadefs_oper = {
1161 	.getattr	= uadefs_getattr,
1162 	.access		= uadefs_access,
1163 	.readlink	= uadefs_readlink,
1164 	.readdir	= uadefs_readdir,
1165 	.mknod		= uadefs_mknod,
1166 	.mkdir		= uadefs_mkdir,
1167 	.symlink	= uadefs_symlink,
1168 	.unlink		= uadefs_unlink,
1169 	.rmdir		= uadefs_rmdir,
1170 	.rename		= uadefs_rename,
1171 	.link		= uadefs_link,
1172 	.chmod		= uadefs_chmod,
1173 	.chown		= uadefs_chown,
1174 	.truncate	= uadefs_truncate,
1175 	.utimens	= uadefs_utimens,
1176 	.open		= uadefs_open,
1177 	.read		= uadefs_read,
1178 	.write		= uadefs_write,
1179 	.statfs		= uadefs_statfs,
1180 	.flush          = uadefs_flush,
1181 	.release	= uadefs_release,
1182 	.fsync		= uadefs_fsync,
1183 #ifdef HAVE_SETXATTR
1184 	.setxattr	= uadefs_setxattr,
1185 	.getxattr	= uadefs_getxattr,
1186 	.listxattr	= uadefs_listxattr,
1187 	.removexattr	= uadefs_removexattr,
1188 #endif
1189 };
1190 
usage(const char * progname)1191 static void usage(const char *progname)
1192 {
1193 	fprintf(stderr,
1194 "usage: %s musicdir mountpoint [options]\n"
1195 "\n"
1196 "general options:\n"
1197 "    -o opt,[opt...]        mount options\n"
1198 "    -h   --help            print help\n"
1199 "    -V   --version         print version\n"
1200 "\n", progname);
1201 }
1202 
1203 enum {
1204 	KEY_HELP,
1205 	KEY_VERSION,
1206 	KEY_FOREGROUND,
1207 };
1208 
1209 static struct fuse_opt uadefs_opts[] = {
1210 	FUSE_OPT_KEY("-V",             KEY_VERSION),
1211 	FUSE_OPT_KEY("--version",      KEY_VERSION),
1212 	FUSE_OPT_KEY("-h",             KEY_HELP),
1213 	FUSE_OPT_KEY("--help",         KEY_HELP),
1214 	FUSE_OPT_KEY("debug",          KEY_FOREGROUND),
1215 	FUSE_OPT_KEY("-d",             KEY_FOREGROUND),
1216 	FUSE_OPT_KEY("-f",             KEY_FOREGROUND),
1217 	FUSE_OPT_END
1218 };
1219 
uadefs_fuse_main(struct fuse_args * args)1220 static int uadefs_fuse_main(struct fuse_args *args)
1221 {
1222 #if FUSE_VERSION >= 26
1223 	return fuse_main(args->argc, args->argv, &uadefs_oper, NULL);
1224 #else
1225 	return fuse_main(args->argc, args->argv, &uadefs_oper);
1226 #endif
1227 }
1228 
uadefs_opt_proc(void * data,const char * arg,int key,struct fuse_args * outargs)1229 static int uadefs_opt_proc(void *data, const char *arg, int key,
1230 			   struct fuse_args *outargs)
1231 {
1232 	(void) data;
1233 	char dname[4096];
1234 
1235 	switch (key) {
1236 	case FUSE_OPT_KEY_OPT:
1237 		return 1;
1238 
1239 	case FUSE_OPT_KEY_NONOPT:
1240 		if (!srcdir) {
1241 			if (arg[0] == '/') {
1242 				srcdir = strdup(arg);
1243 				if (srcdir == NULL)
1244 					DIE("No memory for srcdir\n");
1245 			} else {
1246 				if (getcwd(dname, sizeof dname) == NULL)
1247 					DIE("getcwd() failed\n");
1248 
1249 				if (asprintf(&srcdir, "%s/%s", dname, arg) == -1)
1250 					DIE("asprintf() failed\n");
1251 			}
1252 
1253 			while (1) {
1254 				size_t l = strlen(srcdir);
1255 
1256 				if (l == 1 && srcdir[0] == '/')
1257 					break;
1258 
1259 				if (srcdir[l - 1] != '/')
1260 					break;
1261 
1262 				srcdir[l - 1] = 0;
1263 			}
1264 
1265 			return 0;
1266 		}
1267 		return 1;
1268 
1269 	case KEY_HELP:
1270 		usage(outargs->argv[0]);
1271 		fuse_opt_add_arg(outargs, "-ho");
1272 		uadefs_fuse_main(outargs);
1273 		exit(1);
1274 
1275 	case KEY_VERSION:
1276 		fprintf(stderr, "uadefs version %s\n", UADE_VERSION);
1277 #if FUSE_VERSION >= 25
1278 		fuse_opt_add_arg(outargs, "--version");
1279 		uadefs_fuse_main(outargs);
1280 #endif
1281 		exit(0);
1282 
1283 	case KEY_FOREGROUND:
1284 		debugmode = 1;
1285 		return 1;
1286 
1287 	default:
1288 		fprintf(stderr, "internal error\n");
1289 		abort();
1290 	}
1291 
1292 	return 0;
1293 }
1294 
init_uade(void)1295 static void init_uade(void)
1296 {
1297     char uadeconfname[4096];
1298 
1299     (void) uade_load_initial_config(uadeconfname, sizeof uadeconfname,
1300 				    &uadestate.config, NULL);
1301 
1302     load_content_db();
1303 }
1304 
1305 
main(int argc,char * argv[])1306 int main(int argc, char *argv[])
1307 {
1308 	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
1309 
1310 	if (fuse_opt_parse(&args, NULL, uadefs_opts, uadefs_opt_proc) == -1)
1311 		exit(1);
1312 
1313 	DEBUG("srcdir: %s\n", srcdir);
1314 
1315 	if (getenv("HOME")) {
1316 		int flags = O_WRONLY | O_TRUNC | O_APPEND | O_CREAT;
1317 		int fmode = S_IRUSR | S_IWUSR;
1318 		char logfname[4096];
1319 
1320 		snprintf(logfname, sizeof logfname, "%s/.uade2/uadefs.log", getenv("HOME"));
1321 		debugfd = open(logfname, flags, fmode);
1322 	}
1323 
1324 	init_uade();
1325 
1326 	umask(0);
1327 	return uadefs_fuse_main(&args);
1328 }
1329