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