xref: /netbsd-src/share/examples/puffs/rot13fs/rot13fs.c (revision fc978808f9f061b62f9987456a8ce5404e4db4ee)
1*fc978808Schristos /*	$NetBSD: rot13fs.c,v 1.17 2008/09/12 14:40:47 christos Exp $	*/
2b5da39feSpooka 
3b5da39feSpooka /*
4b5da39feSpooka  * Copyright (c) 2007  Antti Kantee.  All Rights Reserved.
5b5da39feSpooka  *
6b5da39feSpooka  * Redistribution and use in source and binary forms, with or without
7b5da39feSpooka  * modification, are permitted provided that the following conditions
8b5da39feSpooka  * are met:
9b5da39feSpooka  * 1. Redistributions of source code must retain the above copyright
10b5da39feSpooka  *    notice, this list of conditions and the following disclaimer.
11b5da39feSpooka  * 2. Redistributions in binary form must reproduce the above copyright
12b5da39feSpooka  *    notice, this list of conditions and the following disclaimer in the
13b5da39feSpooka  *    documentation and/or other materials provided with the distribution.
14b5da39feSpooka  *
15b5da39feSpooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16b5da39feSpooka  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17b5da39feSpooka  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18b5da39feSpooka  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19b5da39feSpooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20b5da39feSpooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21b5da39feSpooka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22b5da39feSpooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23b5da39feSpooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24b5da39feSpooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25b5da39feSpooka  * SUCH DAMAGE.
26b5da39feSpooka  */
27b5da39feSpooka 
28b5da39feSpooka /*
29b5da39feSpooka  * rot13fs: puffs layering experiment
30b5da39feSpooka  * (unfinished, as is probably fairly easy to tell)
313aa77bc9Spooka  *
323aa77bc9Spooka  * This also demonstrates how namemod can be easily set to any
333aa77bc9Spooka  * function which reverses itself (argument -f provides a case-flipping
343aa77bc9Spooka  * file system).
35b5da39feSpooka  */
36b5da39feSpooka 
373aa77bc9Spooka #include <ctype.h>
38b5da39feSpooka #include <err.h>
39b5da39feSpooka #include <errno.h>
40b5da39feSpooka #include <puffs.h>
41b5da39feSpooka #include <stdio.h>
42b5da39feSpooka #include <stdlib.h>
43b5da39feSpooka #include <unistd.h>
44b5da39feSpooka 
45b5da39feSpooka PUFFSOP_PROTOS(rot13)
46b5da39feSpooka 
47b5da39feSpooka static void usage(void);
48b5da39feSpooka 
49b5da39feSpooka static void
usage()50b5da39feSpooka usage()
51b5da39feSpooka {
52b5da39feSpooka 
53*fc978808Schristos 	errx(1, "usage: %s [-s] [-o mntopts] rot13path mountpath",
54b5da39feSpooka 	    getprogname());
55b5da39feSpooka }
56b5da39feSpooka 
573aa77bc9Spooka static void (*flipflop)(void *, size_t);
583aa77bc9Spooka 
59b5da39feSpooka static uint8_t tbl[256];
60b5da39feSpooka 
61b5da39feSpooka static void
dorot13(void * buf,size_t buflen)62b5da39feSpooka dorot13(void *buf, size_t buflen)
63b5da39feSpooka {
64b5da39feSpooka 	uint8_t *b = buf;
65b5da39feSpooka 
66b5da39feSpooka 	while (buflen--) {
67b5da39feSpooka 		*b = tbl[*b];
68b5da39feSpooka 		b++;
69b5da39feSpooka 	}
70b5da39feSpooka }
71b5da39feSpooka 
723aa77bc9Spooka static void
docase(void * buf,size_t buflen)733aa77bc9Spooka docase(void *buf, size_t buflen)
743aa77bc9Spooka {
753aa77bc9Spooka 	unsigned char *b = buf;
763aa77bc9Spooka 
773aa77bc9Spooka 	while (buflen--) {
783aa77bc9Spooka 		if (isalpha(*b))
793aa77bc9Spooka 			*b ^= 0x20;
803aa77bc9Spooka 		b++;
813aa77bc9Spooka 	}
823aa77bc9Spooka }
833aa77bc9Spooka 
84b5da39feSpooka static int
rot13path(struct puffs_usermount * pu,struct puffs_pathobj * base,struct puffs_cn * pcn)85b5da39feSpooka rot13path(struct puffs_usermount *pu, struct puffs_pathobj *base,
86b5da39feSpooka 	struct puffs_cn *pcn)
87b5da39feSpooka {
88b5da39feSpooka 
893aa77bc9Spooka 	flipflop(pcn->pcn_name, pcn->pcn_namelen);
90b5da39feSpooka 
91b5da39feSpooka 	return 0;
92b5da39feSpooka }
93b5da39feSpooka 
94b5da39feSpooka int
main(int argc,char * argv[])95b5da39feSpooka main(int argc, char *argv[])
96b5da39feSpooka {
97b5da39feSpooka 	struct puffs_usermount *pu;
98b5da39feSpooka 	struct puffs_ops *pops;
99b5da39feSpooka 	struct puffs_pathobj *po_root;
10095a18d20Spooka 	struct puffs_node *pn_root;
101b5da39feSpooka 	struct stat sb;
102b5da39feSpooka 	mntoptparse_t mp;
1034b0f2948Spooka 	int mntflags, pflags;
1044b0f2948Spooka 	int detach;
105b5da39feSpooka 	int ch;
106b5da39feSpooka 	int i;
107b5da39feSpooka 
108b5da39feSpooka 	setprogname(argv[0]);
109b5da39feSpooka 
110b5da39feSpooka 	if (argc < 3)
111b5da39feSpooka 		usage();
112b5da39feSpooka 
1133aa77bc9Spooka 	flipflop = dorot13;
1144b0f2948Spooka 	pflags = mntflags = 0;
1154b0f2948Spooka 	detach = 1;
1163aa77bc9Spooka 	while ((ch = getopt(argc, argv, "fo:s")) != -1) {
117b5da39feSpooka 		switch (ch) {
1183aa77bc9Spooka 		case 'f':
1193aa77bc9Spooka 			flipflop = docase;
1203aa77bc9Spooka 			break;
121b5da39feSpooka 		case 'o':
122b5da39feSpooka 			mp = getmntopts(optarg, puffsmopts, &mntflags, &pflags);
123b5da39feSpooka 			if (mp == NULL)
124b5da39feSpooka 				err(1, "getmntopts");
125b5da39feSpooka 			freemntopts(mp);
126b5da39feSpooka 			break;
127b5da39feSpooka 		case 's':
1284b0f2948Spooka 			detach = 0;
129b5da39feSpooka 			break;
130b5da39feSpooka 		}
131b5da39feSpooka 	}
132b5da39feSpooka 	pflags |= PUFFS_FLAG_BUILDPATH;
133b5da39feSpooka 	argv += optind;
134b5da39feSpooka 	argc -= optind;
135b5da39feSpooka 
136b5da39feSpooka 	if (pflags & PUFFS_FLAG_OPDUMP)
1374b0f2948Spooka 		detach = 0;
138b5da39feSpooka 
139b5da39feSpooka 	if (argc != 2)
140b5da39feSpooka 		usage();
141b5da39feSpooka 
142c8b0a891Spooka 	if (lstat(argv[0], &sb) == -1)
143c8b0a891Spooka 		err(1, "stat %s", argv[0]);
144c8b0a891Spooka 	if ((sb.st_mode & S_IFDIR) == 0)
145c8b0a891Spooka 		errx(1, "%s is not a directory", argv[0]);
146c8b0a891Spooka 
147b5da39feSpooka 	PUFFSOP_INIT(pops);
1480d05db1cSpooka 	puffs_null_setops(pops);
149b5da39feSpooka 
150b5da39feSpooka 	PUFFSOP_SET(pops, rot13, node, readdir);
151b5da39feSpooka 	PUFFSOP_SET(pops, rot13, node, read);
152b5da39feSpooka 	PUFFSOP_SET(pops, rot13, node, write);
153b5da39feSpooka 
15408db7d75Spooka 	if ((pu = puffs_init(pops, argv[0], "rot13", NULL, pflags)) == NULL)
155b5da39feSpooka 		err(1, "mount");
156b5da39feSpooka 
15795a18d20Spooka 	pn_root = puffs_pn_new(pu, NULL);
15895a18d20Spooka 	if (pn_root == NULL)
159b5da39feSpooka 		err(1, "puffs_pn_new");
16095a18d20Spooka 	puffs_setroot(pu, pn_root);
161b5da39feSpooka 
162b5da39feSpooka 	po_root = puffs_getrootpathobj(pu);
163b5da39feSpooka 	if (po_root == NULL)
164b5da39feSpooka 		err(1, "getrootpathobj");
165b5da39feSpooka 	po_root->po_path = argv[0];
166b5da39feSpooka 	po_root->po_len = strlen(argv[0]);
167c8b0a891Spooka 	puffs_stat2vattr(&pn_root->pn_va, &sb);
168b5da39feSpooka 
169b5da39feSpooka 	puffs_set_namemod(pu, rot13path);
170b5da39feSpooka 
171b5da39feSpooka 	/* initialize rot13 tables */
172b5da39feSpooka 	for (i = 0; i < 256; i++)
173b5da39feSpooka 		tbl[i] = (uint8_t)i;
174b5da39feSpooka 	for (i = 0; i <= 26; i++)
175b5da39feSpooka 		tbl[i + 'a'] = 'a' + ((i + 13) % 26);
176b5da39feSpooka 	for (i = 0; i < 26; i++)
177b5da39feSpooka 		tbl[i + 'A'] = 'A' + ((i + 13) % 26);
178b5da39feSpooka 
1794b0f2948Spooka 	if (detach)
1804462e945Spooka 		if (puffs_daemon(pu, 1, 1) == -1)
1814462e945Spooka 			err(1, "puffs_daemon");
1824b0f2948Spooka 
183ec865a5bSpooka 	if (puffs_mount(pu, argv[1], mntflags, pn_root) == -1)
184ec865a5bSpooka 		err(1, "puffs_mount");
1854b0f2948Spooka 	if (puffs_mainloop(pu) == -1)
186ec865a5bSpooka 		err(1, "mainloop");
1874b0f2948Spooka 
1884b0f2948Spooka 	return 0;
189b5da39feSpooka }
190b5da39feSpooka 
191b5da39feSpooka int
rot13_node_readdir(struct puffs_usermount * pu,void * opc,struct dirent * dent,off_t * readoff,size_t * reslen,const struct puffs_cred * pcr,int * eofflag,off_t * cookies,size_t * ncookies)19221913eabSpooka rot13_node_readdir(struct puffs_usermount *pu, void *opc, struct dirent *dent,
1937ed53cb9Spooka 	off_t *readoff, size_t *reslen, const struct puffs_cred *pcr,
1947ed53cb9Spooka 	int *eofflag, off_t *cookies, size_t *ncookies)
195b5da39feSpooka {
196b5da39feSpooka 	struct dirent *dp;
197b5da39feSpooka 	size_t rl;
198b5da39feSpooka 	int rv;
199b5da39feSpooka 
200b5da39feSpooka 	dp = dent;
201b5da39feSpooka 	rl = *reslen;
202b5da39feSpooka 
20321913eabSpooka 	rv = puffs_null_node_readdir(pu, opc, dent, readoff, reslen, pcr,
2047ed53cb9Spooka 	    eofflag, cookies, ncookies);
205b5da39feSpooka 	if (rv)
206b5da39feSpooka 		return rv;
207b5da39feSpooka 
208b5da39feSpooka 	while (rl > *reslen) {
2093aa77bc9Spooka 		flipflop((uint8_t *)dp->d_name, dp->d_namlen);
210b5da39feSpooka 		rl -= _DIRENT_SIZE(dp);
211b5da39feSpooka 		dp = _DIRENT_NEXT(dp);
212b5da39feSpooka 	}
213b5da39feSpooka 
214b5da39feSpooka 	return 0;
215b5da39feSpooka }
216b5da39feSpooka 
217b5da39feSpooka int
rot13_node_read(struct puffs_usermount * pu,void * opc,uint8_t * buf,off_t offset,size_t * resid,const struct puffs_cred * pcr,int ioflag)21821913eabSpooka rot13_node_read(struct puffs_usermount *pu, void *opc,
21921913eabSpooka 	uint8_t *buf, off_t offset, size_t *resid,
22021913eabSpooka 	const struct puffs_cred *pcr, int ioflag)
221b5da39feSpooka {
222b5da39feSpooka 	uint8_t *prebuf = buf;
223b5da39feSpooka 	size_t preres = *resid;
224b5da39feSpooka 	int rv;
225b5da39feSpooka 
22621913eabSpooka 	rv = puffs_null_node_read(pu, opc, buf, offset, resid, pcr, ioflag);
227b5da39feSpooka 	if (rv)
228b5da39feSpooka 		return rv;
229b5da39feSpooka 
2303aa77bc9Spooka 	flipflop(prebuf, preres - *resid);
231b5da39feSpooka 
232b5da39feSpooka 	return rv;
233b5da39feSpooka }
234b5da39feSpooka 
235b5da39feSpooka int
rot13_node_write(struct puffs_usermount * pu,void * opc,uint8_t * buf,off_t offset,size_t * resid,const struct puffs_cred * pcr,int ioflag)23621913eabSpooka rot13_node_write(struct puffs_usermount *pu, void *opc,
23721913eabSpooka 	uint8_t *buf, off_t offset, size_t *resid,
23821913eabSpooka 	const struct puffs_cred *pcr, int ioflag)
239b5da39feSpooka {
240b5da39feSpooka 
2413aa77bc9Spooka 	flipflop(buf, *resid);
24221913eabSpooka 	return puffs_null_node_write(pu, opc, buf, offset, resid, pcr, ioflag);
243b5da39feSpooka }
244