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 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 63 usage(void) 64 { 65 (void) fprintf(stderr, "usage: %s [-v] file\n", 66 __progname); 67 exit(1); 68 } 69 70 int 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