xref: /illumos-gate/usr/src/test/zfs-tests/cmd/dos_ro/dos_ro.c (revision 2889ec41c05e9ffe1890b529b3111354da325aeb)
1*2889ec41SGordon Ross /*
2*2889ec41SGordon Ross  * This file and its contents are supplied under the terms of the
3*2889ec41SGordon Ross  * Common Development and Distribution License ("CDDL"), version 1.0.
4*2889ec41SGordon Ross  * You may only use this file in accordance with the terms of version
5*2889ec41SGordon Ross  * 1.0 of the CDDL.
6*2889ec41SGordon Ross  *
7*2889ec41SGordon Ross  * A full copy of the text of the CDDL should have accompanied this
8*2889ec41SGordon Ross  * source.  A copy of the CDDL is also available via the Internet at
9*2889ec41SGordon Ross  * http://www.illumos.org/license/CDDL.
10*2889ec41SGordon Ross  */
11*2889ec41SGordon Ross 
12*2889ec41SGordon Ross /*
13*2889ec41SGordon Ross  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
14*2889ec41SGordon Ross  */
15*2889ec41SGordon Ross 
16*2889ec41SGordon Ross #include <sys/types.h>
17*2889ec41SGordon Ross #include <sys/stat.h>
18*2889ec41SGordon Ross 
19*2889ec41SGordon Ross #include <attr.h>
20*2889ec41SGordon Ross #include <errno.h>
21*2889ec41SGordon Ross #include <fcntl.h>
22*2889ec41SGordon Ross #include <stdio.h>
23*2889ec41SGordon Ross #include <stdlib.h>
24*2889ec41SGordon Ross #include <unistd.h>
25*2889ec41SGordon Ross #include <libnvpair.h>
26*2889ec41SGordon Ross 
27*2889ec41SGordon Ross extern const char *__progname;
28*2889ec41SGordon Ross 
29*2889ec41SGordon Ross int vflag = 0;
30*2889ec41SGordon Ross 
31*2889ec41SGordon Ross static int
dosattr_set_ro(int fildes,const char * fname)32*2889ec41SGordon Ross dosattr_set_ro(int fildes, const char *fname)
33*2889ec41SGordon Ross {
34*2889ec41SGordon Ross 	nvlist_t	*nvl = NULL;
35*2889ec41SGordon Ross 	int		err;
36*2889ec41SGordon Ross 
37*2889ec41SGordon Ross 	err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0);
38*2889ec41SGordon Ross 	if (err != 0)
39*2889ec41SGordon Ross 		return (err);
40*2889ec41SGordon Ross 
41*2889ec41SGordon Ross 	(void) nvlist_add_boolean_value(nvl, A_READONLY, 1);
42*2889ec41SGordon Ross 
43*2889ec41SGordon Ross 	if (fname == NULL) {
44*2889ec41SGordon Ross 		err = fsetattr(fildes, XATTR_VIEW_READWRITE, nvl);
45*2889ec41SGordon Ross 	} else {
46*2889ec41SGordon Ross 		err = setattrat(fildes, XATTR_VIEW_READWRITE, fname, nvl);
47*2889ec41SGordon Ross 	}
48*2889ec41SGordon Ross 	if (err < 0) {
49*2889ec41SGordon Ross 		err = errno;
50*2889ec41SGordon Ross 		if (vflag > 1) {
51*2889ec41SGordon Ross 			(void) fprintf(stderr,
52*2889ec41SGordon Ross 			    "dosattr_set: setattrat (%s), err %d\n",
53*2889ec41SGordon Ross 			    fname, err);
54*2889ec41SGordon Ross 		}
55*2889ec41SGordon Ross 	}
56*2889ec41SGordon Ross 
57*2889ec41SGordon Ross 	nvlist_free(nvl);
58*2889ec41SGordon Ross 
59*2889ec41SGordon Ross 	return (err);
60*2889ec41SGordon Ross }
61*2889ec41SGordon Ross 
62*2889ec41SGordon Ross void
usage(void)63*2889ec41SGordon Ross usage(void)
64*2889ec41SGordon Ross {
65*2889ec41SGordon Ross 	(void) fprintf(stderr, "usage: %s [-v] file\n",
66*2889ec41SGordon Ross 	    __progname);
67*2889ec41SGordon Ross 	exit(1);
68*2889ec41SGordon Ross }
69*2889ec41SGordon Ross 
70*2889ec41SGordon Ross int
main(int argc,char ** argv)71*2889ec41SGordon Ross main(int argc, char **argv)
72*2889ec41SGordon Ross {
73*2889ec41SGordon Ross 	char *fname;
74*2889ec41SGordon Ross 	int c, fd, n;
75*2889ec41SGordon Ross 
76*2889ec41SGordon Ross 	while ((c = getopt(argc, argv, "v")) != -1) {
77*2889ec41SGordon Ross 		switch (c) {
78*2889ec41SGordon Ross 		case 'v':
79*2889ec41SGordon Ross 			vflag++;
80*2889ec41SGordon Ross 			break;
81*2889ec41SGordon Ross 		case '?':
82*2889ec41SGordon Ross 		default:
83*2889ec41SGordon Ross 			usage();
84*2889ec41SGordon Ross 			break;
85*2889ec41SGordon Ross 		}
86*2889ec41SGordon Ross 	}
87*2889ec41SGordon Ross 
88*2889ec41SGordon Ross 	if (optind + 1 != argc)
89*2889ec41SGordon Ross 		usage();
90*2889ec41SGordon Ross 	fname = argv[optind];
91*2889ec41SGordon Ross 
92*2889ec41SGordon Ross 	fd = open(fname, O_CREAT | O_RDWR, 0644);
93*2889ec41SGordon Ross 	if (fd < 0) {
94*2889ec41SGordon Ross 		perror(fname);
95*2889ec41SGordon Ross 		exit(1);
96*2889ec41SGordon Ross 	}
97*2889ec41SGordon Ross 
98*2889ec41SGordon Ross 	if (vflag)
99*2889ec41SGordon Ross 		(void) fprintf(stderr, "Write 1 (mode 644)\n");
100*2889ec41SGordon Ross 	n = write(fd, "mode 644 OK\n", 12);
101*2889ec41SGordon Ross 	if (n != 12) {
102*2889ec41SGordon Ross 		(void) fprintf(stderr, "write mode 644, err=%d\n", errno);
103*2889ec41SGordon Ross 		exit(1);
104*2889ec41SGordon Ross 	}
105*2889ec41SGordon Ross 
106*2889ec41SGordon Ross 	if (vflag)
107*2889ec41SGordon Ross 		(void) fprintf(stderr, "Chmod 444\n");
108*2889ec41SGordon Ross 	n = fchmod(fd, 0444);
109*2889ec41SGordon Ross 	if (n < 0) {
110*2889ec41SGordon Ross 		(void) fprintf(stderr, "chmod 444, err=%d\n", errno);
111*2889ec41SGordon Ross 		exit(1);
112*2889ec41SGordon Ross 	}
113*2889ec41SGordon Ross 
114*2889ec41SGordon Ross 	if (vflag)
115*2889ec41SGordon Ross 		(void) fprintf(stderr, "Write 2 (mode 444)\n");
116*2889ec41SGordon Ross 	n = write(fd, "mode 444 OK\n", 12);
117*2889ec41SGordon Ross 	if (n != 12) {
118*2889ec41SGordon Ross 		(void) fprintf(stderr, "write mode 444, err=%d\n", errno);
119*2889ec41SGordon Ross 		exit(1);
120*2889ec41SGordon Ross 	}
121*2889ec41SGordon Ross 
122*2889ec41SGordon Ross 	if (vflag)
123*2889ec41SGordon Ross 		(void) fprintf(stderr, "Set DOS R/O\n");
124*2889ec41SGordon Ross 	n = dosattr_set_ro(fd, NULL /* fname? */);
125*2889ec41SGordon Ross 	if (n != 0) {
126*2889ec41SGordon Ross 		(void) fprintf(stderr, "Set R/O, err=%d\n", n);
127*2889ec41SGordon Ross 		exit(1);
128*2889ec41SGordon Ross 	}
129*2889ec41SGordon Ross 
130*2889ec41SGordon Ross 	/*
131*2889ec41SGordon Ross 	 * This fails, but write on an already open handle should succeed
132*2889ec41SGordon Ross 	 * the same as when we've set the mode to 444 after open.
133*2889ec41SGordon Ross 	 */
134*2889ec41SGordon Ross 	if (vflag)
135*2889ec41SGordon Ross 		(void) fprintf(stderr, "Write 3 (DOS R/O)\n");
136*2889ec41SGordon Ross 	n = write(fd, "Write DOS RO?\n", 14);
137*2889ec41SGordon Ross 	if (n != 14) {
138*2889ec41SGordon Ross 		(void) fprintf(stderr, "write (DOS R/O), err=%d\n", errno);
139*2889ec41SGordon Ross 		exit(1);
140*2889ec41SGordon Ross 	}
141*2889ec41SGordon Ross 
142*2889ec41SGordon Ross 	return (0);
143*2889ec41SGordon Ross }
144