1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * rmf_misc.c :
29 * Miscelleneous routines for rmformat.
30 */
31
32 #include <sys/types.h>
33 #include <stdio.h>
34 #include <sys/mnttab.h>
35 #include <volmgt.h>
36 #include <sys/dkio.h>
37 #include <sys/fdio.h>
38 #include <sys/vtoc.h>
39 #include <sys/termios.h>
40 #include <sys/mount.h>
41 #include <ctype.h>
42 #include <signal.h>
43 #include <sys/wait.h>
44 #include <dirent.h>
70 static struct uscsi_cmd uscmd;
71 static char ucdb[16];
72 uchar_t uscsi_status, rqstatus, rqresid;
73 int total_devices_found = 0;
74 int removable_found = 0;
75
76 extern char *global_intr_msg;
77 extern int vol_running;
78 extern char *dev_name;
79 extern int32_t m_flag;
80
81 /*
82 * ON-private functions from libvolmgt
83 */
84 int _dev_mounted(char *path);
85
86 /*
87 * Function prototypes.
88 */
89 static int my_umount(char *mountp);
90 static int my_volrmmount(char *real_name);
91 static int vol_name_to_dev_node(char *vname, char *found);
92 static int vol_lookup(char *supplied, char *found);
93 static device_t *get_device(char *user_supplied, char *node);
94 static char *get_physical_name(char *path);
95 static int lookup_device(char *supplied, char *found);
96 static void fini_device(device_t *dev);
97 static int is_cd(char *node);
98 void *my_zalloc(size_t size);
99 void err_msg(char *fmt, ...);
100 int inquiry(int fd, uchar_t *inq);
101 struct uscsi_cmd *get_uscsi_cmd(void);
102 int uscsi(int fd, struct uscsi_cmd *scmd);
103 int get_mode_page(int fd, int page_no, int pc, int buf_len,
104 uchar_t *buffer);
105 int mode_sense(int fd, uchar_t pc, int dbd, int page_len,
106 uchar_t *buffer);
107 uint16_t read_scsi16(void *addr);
108 int check_device(device_t *dev, int cond);
109 static void get_media_info(device_t *t_dev, char *sdev,
110 char *pname, char *sn);
244 if ((nm = volmgt_symname(device_name)) == NULL) {
245 DPRINTF("path not managed\n");
246 real_name = media_findname(device_name);
247 } else {
248 DPRINTF1("path managed as %s\n", nm);
249 real_name = media_findname(nm);
250 DPRINTF1("real name %s\n", real_name);
251 }
252
253 if (real_name == NULL)
254 return (-1);
255
256 /*
257 * To find out whether the device has been mounted by
258 * volume manager...
259 *
260 * Convert the real name to a block device address.
261 * Do a partial match with the mnttab entries.
262 * Make sure the match is in the beginning to avoid if
263 * anybody puts a label similiar to volume manager path names.
264 * Then use "volrmmount -e <dev_name>" if -U flag is set.
265 */
266
267 nl = strlen("/vol/dev/");
268
269 if (strncmp(real_name, "/vol/dev/", nl) != 0)
270 return (0);
271 if (real_name[nl] == 'r') {
272 (void) snprintf(tmp_path_name, PATH_MAX, "%s%s", "/vol/dev/",
273 &real_name[nl + 1]);
274 } else {
275 (void) snprintf(tmp_path_name, PATH_MAX, "%s", real_name);
276 }
277 DPRINTF1("%s \n", tmp_path_name);
278 ret_val = stat(tmp_path_name, &stat_buf);
279 if (ret_val < 0) {
280 PERROR("Could not stat");
281 return (-1);
282 }
283
284 fp = fopen("/etc/mnttab", "r");
299 if (errno != 0) {
300 PERROR("Error with mnttab");
301 (void) fclose(fp);
302 return (-1);
303 }
304 /* Is it a probable entry? */
305 DPRINTF1(" %s \n", mntp->mnt_special);
306 if (strstr(mntp->mnt_special, tmp_path_name) !=
307 mntp->mnt_special) {
308 /* Skip to next entry */
309 continue;
310 } else {
311 DPRINTF1("Found!! %s\n", mntp->mnt_special);
312 ret_val = 1;
313 break;
314 }
315 }
316
317 if (ret_val == 1) {
318 if (flag) {
319 if (my_volrmmount(real_name) < 0) {
320 ret_val = -1;
321 }
322 } else {
323 ret_val = -1;
324 }
325 }
326 (void) fclose(fp);
327 free(mntp);
328 return (ret_val);
329 }
330
331 /*
332 * This routine checks if a device has mounted partitions. The
333 * device name is assumed to be /dev/rdsk/cNtNdNsN. So, this can
334 * be used for SCSI and PCMCIA cards.
335 * Returns
336 * 0 : if not mounted
337 * 1 : if successfully unmounted
338 * -1 : Any error or umount failed
339 */
1051 /* Turn off the privileges */
1052 (void) __priv_bracket(PRIV_OFF);
1053 exit(-1);
1054 }
1055 }
1056
1057 /* wait for the umount command to exit */
1058 rval = 0;
1059 if (waitpid(pid, &rval, 0) == pid) {
1060 if (WIFEXITED(rval)) {
1061 if (WEXITSTATUS(rval) == 0) {
1062 DPRINTF("umount : Success\n");
1063 return (1);
1064 }
1065 }
1066 }
1067 return (-1);
1068 }
1069
1070 static int
1071 my_volrmmount(char *real_name)
1072 {
1073 int pid, rval;
1074
1075 /* Turn on the privileges. */
1076 (void) __priv_bracket(PRIV_ON);
1077
1078 pid = fork();
1079
1080 /* Turn off the privileges. */
1081 (void) __priv_bracket(PRIV_OFF);
1082
1083 /* create a child to unmount the path */
1084 if (pid < 0) {
1085 PERROR("fork failed");
1086 exit(0);
1087 }
1088
1089 if (pid == 0) {
1090 /* the child */
1091 /* get rid of those nasty err messages */
1092 DPRINTF1("call_unmount_prog: calling %s \n",
1093 "/usr/bin/volrmmount");
1094
1095 /* Turn on the privileges. */
1096 (void) __priv_bracket(PRIV_ON);
1097 if (execl("/usr/bin/volrmmount", "/usr/bin/volrmmount", "-e",
1098 real_name, NULL) < 0) {
1099 PERROR("volrmmount exec failed");
1100 /* Turn off the privileges */
1101 (void) __priv_bracket(PRIV_OFF);
1102 exit(-1);
1103 }
1104 } else if (waitpid(pid, &rval, 0) == pid) {
1105 if (WIFEXITED(rval)) {
1106 if (WEXITSTATUS(rval) == 0) {
1107 DPRINTF("volrmmount: Success\n");
1108 return (1);
1109 }
1110 }
1111 }
1112 return (-1);
1113 }
1114
1115 int
1116 find_device(int defer, char *tmpstr)
1117 {
1118 DIR *dir;
1119 struct dirent *dirent;
1120 char sdev[PATH_MAX], dev[PATH_MAX], *pname;
1121 device_t *t_dev;
1122 int removable = 0;
1123 int device_type = 0;
1124 int hotpluggable = 0;
1125 struct dk_minfo mediainfo;
1126 static int found = 0;
1127
1143 #else /* x86 */
1144 if (vol_running) {
1145 if (!(strstr(sdev, "s2") || strstr(sdev, "p0"))) {
1146 continue;
1147 }
1148 } else {
1149 if (!strstr(sdev, "p0")) {
1150 continue;
1151 }
1152 }
1153 #endif
1154 if (!lookup_device(sdev, dev)) {
1155 continue;
1156 }
1157 if ((t_dev = get_device(NULL, dev)) == NULL) {
1158 continue;
1159 }
1160 total_devices_found++;
1161
1162 if ((!defer) && !found) {
1163 char *sn, *tmpbuf;
1164 /*
1165 * dev_name is an optional command line input.
1166 */
1167 if (dev_name) {
1168 if (strstr(dirent->d_name, tmpstr)) {
1169 found = 1;
1170 } else if (!vol_running) {
1171 continue;
1172 }
1173 }
1174 /*
1175 * volmgt_symname() returns NULL if the device
1176 * is not managed by volmgt.
1177 */
1178 sn = volmgt_symname(sdev);
1179
1180 if (vol_running && (sn != NULL)) {
1181 if (strstr(sn, "dev") == NULL) {
1182 tmpbuf = (char *)my_zalloc(PATH_MAX);
1183 (void) strcpy(tmpbuf,
|
1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 *
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 *
25 * Copyright 2014 Andrew Stormont.
26 */
27
28 /*
29 * rmf_misc.c :
30 * Miscelleneous routines for rmformat.
31 */
32
33 #include <sys/types.h>
34 #include <stdio.h>
35 #include <sys/mnttab.h>
36 #include <volmgt.h>
37 #include <sys/dkio.h>
38 #include <sys/fdio.h>
39 #include <sys/vtoc.h>
40 #include <sys/termios.h>
41 #include <sys/mount.h>
42 #include <ctype.h>
43 #include <signal.h>
44 #include <sys/wait.h>
45 #include <dirent.h>
71 static struct uscsi_cmd uscmd;
72 static char ucdb[16];
73 uchar_t uscsi_status, rqstatus, rqresid;
74 int total_devices_found = 0;
75 int removable_found = 0;
76
77 extern char *global_intr_msg;
78 extern int vol_running;
79 extern char *dev_name;
80 extern int32_t m_flag;
81
82 /*
83 * ON-private functions from libvolmgt
84 */
85 int _dev_mounted(char *path);
86
87 /*
88 * Function prototypes.
89 */
90 static int my_umount(char *mountp);
91 static int my_rmmount(char *real_name);
92 static int vol_name_to_dev_node(char *vname, char *found);
93 static int vol_lookup(char *supplied, char *found);
94 static device_t *get_device(char *user_supplied, char *node);
95 static char *get_physical_name(char *path);
96 static int lookup_device(char *supplied, char *found);
97 static void fini_device(device_t *dev);
98 static int is_cd(char *node);
99 void *my_zalloc(size_t size);
100 void err_msg(char *fmt, ...);
101 int inquiry(int fd, uchar_t *inq);
102 struct uscsi_cmd *get_uscsi_cmd(void);
103 int uscsi(int fd, struct uscsi_cmd *scmd);
104 int get_mode_page(int fd, int page_no, int pc, int buf_len,
105 uchar_t *buffer);
106 int mode_sense(int fd, uchar_t pc, int dbd, int page_len,
107 uchar_t *buffer);
108 uint16_t read_scsi16(void *addr);
109 int check_device(device_t *dev, int cond);
110 static void get_media_info(device_t *t_dev, char *sdev,
111 char *pname, char *sn);
245 if ((nm = volmgt_symname(device_name)) == NULL) {
246 DPRINTF("path not managed\n");
247 real_name = media_findname(device_name);
248 } else {
249 DPRINTF1("path managed as %s\n", nm);
250 real_name = media_findname(nm);
251 DPRINTF1("real name %s\n", real_name);
252 }
253
254 if (real_name == NULL)
255 return (-1);
256
257 /*
258 * To find out whether the device has been mounted by
259 * volume manager...
260 *
261 * Convert the real name to a block device address.
262 * Do a partial match with the mnttab entries.
263 * Make sure the match is in the beginning to avoid if
264 * anybody puts a label similiar to volume manager path names.
265 * Then use "rmmount -u <dev_name>" if -U flag is set.
266 */
267
268 nl = strlen("/vol/dev/");
269
270 if (strncmp(real_name, "/vol/dev/", nl) != 0)
271 return (0);
272 if (real_name[nl] == 'r') {
273 (void) snprintf(tmp_path_name, PATH_MAX, "%s%s", "/vol/dev/",
274 &real_name[nl + 1]);
275 } else {
276 (void) snprintf(tmp_path_name, PATH_MAX, "%s", real_name);
277 }
278 DPRINTF1("%s \n", tmp_path_name);
279 ret_val = stat(tmp_path_name, &stat_buf);
280 if (ret_val < 0) {
281 PERROR("Could not stat");
282 return (-1);
283 }
284
285 fp = fopen("/etc/mnttab", "r");
300 if (errno != 0) {
301 PERROR("Error with mnttab");
302 (void) fclose(fp);
303 return (-1);
304 }
305 /* Is it a probable entry? */
306 DPRINTF1(" %s \n", mntp->mnt_special);
307 if (strstr(mntp->mnt_special, tmp_path_name) !=
308 mntp->mnt_special) {
309 /* Skip to next entry */
310 continue;
311 } else {
312 DPRINTF1("Found!! %s\n", mntp->mnt_special);
313 ret_val = 1;
314 break;
315 }
316 }
317
318 if (ret_val == 1) {
319 if (flag) {
320 if (my_rmmount(real_name) < 0) {
321 ret_val = -1;
322 }
323 } else {
324 ret_val = -1;
325 }
326 }
327 (void) fclose(fp);
328 free(mntp);
329 return (ret_val);
330 }
331
332 /*
333 * This routine checks if a device has mounted partitions. The
334 * device name is assumed to be /dev/rdsk/cNtNdNsN. So, this can
335 * be used for SCSI and PCMCIA cards.
336 * Returns
337 * 0 : if not mounted
338 * 1 : if successfully unmounted
339 * -1 : Any error or umount failed
340 */
1052 /* Turn off the privileges */
1053 (void) __priv_bracket(PRIV_OFF);
1054 exit(-1);
1055 }
1056 }
1057
1058 /* wait for the umount command to exit */
1059 rval = 0;
1060 if (waitpid(pid, &rval, 0) == pid) {
1061 if (WIFEXITED(rval)) {
1062 if (WEXITSTATUS(rval) == 0) {
1063 DPRINTF("umount : Success\n");
1064 return (1);
1065 }
1066 }
1067 }
1068 return (-1);
1069 }
1070
1071 static int
1072 my_rmmount(char *real_name)
1073 {
1074 int pid, rval;
1075
1076 /* Turn on the privileges. */
1077 (void) __priv_bracket(PRIV_ON);
1078
1079 pid = fork();
1080
1081 /* Turn off the privileges. */
1082 (void) __priv_bracket(PRIV_OFF);
1083
1084 /* create a child to unmount the path */
1085 if (pid < 0) {
1086 PERROR("fork failed");
1087 exit(0);
1088 }
1089
1090 if (pid == 0) {
1091 /* the child */
1092 /* get rid of those nasty err messages */
1093 DPRINTF1("call_unmount_prog: calling %s\n",
1094 "/usr/bin/rmmount");
1095
1096 /* Turn on the privileges. */
1097 (void) __priv_bracket(PRIV_ON);
1098 if (execl("/usr/bin/rmmount", "/usr/bin/rmmount", "-u",
1099 real_name, NULL) < 0) {
1100 PERROR("rmmount exec failed");
1101 /* Turn off the privileges */
1102 (void) __priv_bracket(PRIV_OFF);
1103 exit(-1);
1104 }
1105 } else if (waitpid(pid, &rval, 0) == pid) {
1106 if (WIFEXITED(rval)) {
1107 if (WEXITSTATUS(rval) == 0) {
1108 DPRINTF("rmmount: Success\n");
1109 return (1);
1110 }
1111 }
1112 }
1113 return (-1);
1114 }
1115
1116 int
1117 find_device(int defer, char *tmpstr)
1118 {
1119 DIR *dir;
1120 struct dirent *dirent;
1121 char sdev[PATH_MAX], dev[PATH_MAX], *pname;
1122 device_t *t_dev;
1123 int removable = 0;
1124 int device_type = 0;
1125 int hotpluggable = 0;
1126 struct dk_minfo mediainfo;
1127 static int found = 0;
1128
1144 #else /* x86 */
1145 if (vol_running) {
1146 if (!(strstr(sdev, "s2") || strstr(sdev, "p0"))) {
1147 continue;
1148 }
1149 } else {
1150 if (!strstr(sdev, "p0")) {
1151 continue;
1152 }
1153 }
1154 #endif
1155 if (!lookup_device(sdev, dev)) {
1156 continue;
1157 }
1158 if ((t_dev = get_device(NULL, dev)) == NULL) {
1159 continue;
1160 }
1161 total_devices_found++;
1162
1163 if ((!defer) && !found) {
1164 char *sn, *tmpbuf = NULL;
1165 /*
1166 * dev_name is an optional command line input.
1167 */
1168 if (dev_name) {
1169 if (strstr(dirent->d_name, tmpstr)) {
1170 found = 1;
1171 } else if (!vol_running) {
1172 continue;
1173 }
1174 }
1175 /*
1176 * volmgt_symname() returns NULL if the device
1177 * is not managed by volmgt.
1178 */
1179 sn = volmgt_symname(sdev);
1180
1181 if (vol_running && (sn != NULL)) {
1182 if (strstr(sn, "dev") == NULL) {
1183 tmpbuf = (char *)my_zalloc(PATH_MAX);
1184 (void) strcpy(tmpbuf,
|