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);
206 buf = fgets(re_passwd, (size_t)256, in);
207 rewind(in);
208 (void) fputc('\n', out);
209 if ((buf == NULL) || strcmp(passwd, re_passwd)) {
210 (void) fputs("passwords did not match\n", out);
211 (void) fputs("Try again\n", out);
212 } else {
213 break;
214 }
215 }
216 wp->sm_passwd_len = len;
217 (void) strncpy(wp->sm_passwd, passwd, wp->sm_passwd_len);
218 wp->sm_version = SMWP_STATE_V_1;
219
220 /* Restore echoing. */
221 if (echo_off)
222 (void) tcsetattr(fileno(in), TCSAFLUSH, &tio);
223
224 }
225
226 int32_t
227 check_and_unmount_vold(char *device_name, int32_t flag)
228 {
229 char *real_name;
230 char *nm;
231 char tmp_path_name[PATH_MAX];
232 struct stat stat_buf;
233 int32_t ret_val = 0;
234 struct mnttab *mntp;
235 FILE *fp;
236 int nl;
237
238 DPRINTF1("Device name %s\n", device_name);
239
240 if (volmgt_running() == 0) {
241 DPRINTF("Vold not running\n");
242 return (0);
243 }
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");
285
286 if (fp == NULL) {
287 PERROR("Could not open /etc/mnttab");
288 return (-1);
289 }
290
291 mntp = (struct mnttab *)malloc(sizeof (struct mnttab));
292 if (mntp == NULL) {
293 PERROR("malloc failed");
294 (void) fclose(fp);
295 return (-1);
296 }
297 errno = 0;
298 while (getmntent(fp, mntp) == 0) {
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 */
340
341 int32_t
342 check_and_unmount_scsi(char *device_name, int32_t flag)
343 {
344
345 struct mnttab *mntrefp;
346 struct mnttab *mntp;
347 FILE *fp;
348 char block_dev_name[PATH_MAX];
349 char tmp_name[PATH_MAX];
350 int32_t i, j;
1050 perror("exec failed");
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
1128 dir = opendir("/dev/rdsk");
1129 if (dir == NULL)
1130 return (-1);
1131
1132 total_devices_found = 0;
1133 while ((dirent = readdir(dir)) != NULL) {
1134 if (dirent->d_name[0] == '.') {
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 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);
206 buf = fgets(re_passwd, (size_t)256, in);
207 rewind(in);
208 (void) fputc('\n', out);
209 if ((buf == NULL) || strcmp(passwd, re_passwd)) {
210 (void) fputs("passwords did not match\n", out);
211 (void) fputs("Try again\n", out);
212 } else {
213 break;
214 }
215 }
216 wp->sm_passwd_len = len;
217 (void) strncpy(wp->sm_passwd, passwd, wp->sm_passwd_len);
218 wp->sm_version = SMWP_STATE_V_1;
219
220 /* Restore echoing. */
221 if (echo_off)
222 (void) tcsetattr(fileno(in), TCSAFLUSH, &tio);
223
224 }
225
226 /*
227 * This routine checks if a device has mounted partitions. The
228 * device name is assumed to be /dev/rdsk/cNtNdNsN. So, this can
229 * be used for SCSI and PCMCIA cards.
230 * Returns
231 * 0 : if not mounted
232 * 1 : if successfully unmounted
233 * -1 : Any error or umount failed
234 */
235
236 int32_t
237 check_and_unmount_scsi(char *device_name, int32_t flag)
238 {
239
240 struct mnttab *mntrefp;
241 struct mnttab *mntp;
242 FILE *fp;
243 char block_dev_name[PATH_MAX];
244 char tmp_name[PATH_MAX];
245 int32_t i, j;
945 perror("exec failed");
946 /* Turn off the privileges */
947 (void) __priv_bracket(PRIV_OFF);
948 exit(-1);
949 }
950 }
951
952 /* wait for the umount command to exit */
953 rval = 0;
954 if (waitpid(pid, &rval, 0) == pid) {
955 if (WIFEXITED(rval)) {
956 if (WEXITSTATUS(rval) == 0) {
957 DPRINTF("umount : Success\n");
958 return (1);
959 }
960 }
961 }
962 return (-1);
963 }
964
965 int
966 find_device(int defer, char *tmpstr)
967 {
968 DIR *dir;
969 struct dirent *dirent;
970 char sdev[PATH_MAX], dev[PATH_MAX], *pname;
971 device_t *t_dev;
972 int removable = 0;
973 int device_type = 0;
974 int hotpluggable = 0;
975 struct dk_minfo mediainfo;
976 static int found = 0;
977
978 dir = opendir("/dev/rdsk");
979 if (dir == NULL)
980 return (-1);
981
982 total_devices_found = 0;
983 while ((dirent = readdir(dir)) != NULL) {
984 if (dirent->d_name[0] == '.') {
993 #else /* x86 */
994 if (vol_running) {
995 if (!(strstr(sdev, "s2") || strstr(sdev, "p0"))) {
996 continue;
997 }
998 } else {
999 if (!strstr(sdev, "p0")) {
1000 continue;
1001 }
1002 }
1003 #endif
1004 if (!lookup_device(sdev, dev)) {
1005 continue;
1006 }
1007 if ((t_dev = get_device(NULL, dev)) == NULL) {
1008 continue;
1009 }
1010 total_devices_found++;
1011
1012 if ((!defer) && !found) {
1013 char *sn, *tmpbuf = NULL;
1014 /*
1015 * dev_name is an optional command line input.
1016 */
1017 if (dev_name) {
1018 if (strstr(dirent->d_name, tmpstr)) {
1019 found = 1;
1020 } else if (!vol_running) {
1021 continue;
1022 }
1023 }
1024 /*
1025 * volmgt_symname() returns NULL if the device
1026 * is not managed by volmgt.
1027 */
1028 sn = volmgt_symname(sdev);
1029
1030 if (vol_running && (sn != NULL)) {
1031 if (strstr(sn, "dev") == NULL) {
1032 tmpbuf = (char *)my_zalloc(PATH_MAX);
1033 (void) strcpy(tmpbuf,
|