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 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <sys/types.h> 28 #include <sys/time.h> 29 #include <errno.h> 30 #include <signal.h> 31 #include <stdio.h> 32 #include <string.h> 33 #include <fcntl.h> 34 #include <stdlib.h> 35 #include <unistd.h> 36 #include <values.h> 37 #include <locale.h> 38 #include <sys/stat.h> 39 #include <strings.h> 40 #include <stdarg.h> 41 #include <sys/param.h> 42 #include <nsctl.h> 43 44 #include <sys/nsctl/cfg.h> 45 #include <sys/unistat/spcs_s.h> 46 #include <sys/unistat/spcs_s_u.h> 47 #include <sys/unistat/spcs_errors.h> 48 #include <sys/nsctl/dsw.h> 49 #include <sys/nsctl/dsw_dev.h> /* for bitmap format */ 50 51 #define DSW_TEXT_DOMAIN "II" 52 #define BITMAP_TOKEN "ii.set%d.bitmap" 53 #define SHADOW_TOKEN "ii.set%d.shadow" 54 #define SV_TOKEN "sv.set%d.vol" 55 #define DSVOL_TOKEN "dsvol.set%d.path" 56 57 void iicpshd_usage(); 58 void copyshd(char *, char *); 59 int find_cfg_info(char *, char *); 60 int copy_shadow_vol(char *, char *); 61 void convert_to_blockdevice(); 62 int update_dscfg(char *); 63 64 extern int optind; 65 66 extern char *optarg; 67 extern int optind, opterr, optopt; 68 int copy_shadow = 1; 69 CFGFILE *cfg; 70 char real_bitmap[DSW_NAMELEN]; 71 char buf[CFG_MAX_BUF]; 72 char key[CFG_MAX_KEY]; 73 int set_number; 74 int sv_number; 75 int dsvol_number; 76 77 #ifdef lint 78 int 79 iicpshd_lintmain(int argc, char *argv[]) 80 #else 81 int 82 main(int argc, char *argv[]) 83 #endif 84 { 85 if (argc > 1) { 86 if (strcmp(argv[1], "-s") == 0) { 87 /* don't copy shadow, only update dscfg and ii header */ 88 copy_shadow = 0; 89 argc--; 90 argv++; 91 } 92 } 93 94 if (argc == 1 || (argc%2) == 0) /* must have pairs of filenames */ 95 iicpshd_usage(); 96 97 /* open dscfg anyway */ 98 if ((cfg = cfg_open(NULL)) == NULL) { 99 (void) fprintf(stderr, gettext("Error opening config\n")); 100 exit(1); 101 } 102 103 for (argv++; *argv != NULL; argv += 2) 104 copyshd(argv[0], argv[1]); 105 106 /* close dscfg */ 107 cfg_close(cfg); 108 exit(0); 109 return (0); 110 } 111 112 void 113 iicpshd_usage() 114 { 115 (void) fprintf(stderr, gettext("Usage:\n")); 116 (void) fprintf(stderr, 117 gettext("\tiicpshd [-s] old_shadow new_shadow\n")); 118 exit(1); 119 } 120 121 void 122 copyshd(char *old_vol, char *new_vol) 123 { 124 int dsw_fd; 125 FILE *ifp; 126 char header[FBA_SIZE(1) * DSW_CBLK_FBA]; 127 ii_header_t *hp; 128 dsw_stat_t args; 129 130 /*LINTED pointer alignment*/ 131 hp = (ii_header_t *)&header; 132 133 dsw_fd = open(DSWDEV, O_RDONLY); 134 if (dsw_fd < 0) { 135 perror(DSWDEV); 136 exit(1); 137 } 138 if (*old_vol != '/' || *new_vol != '/') { 139 (void) fprintf(stderr, gettext("Both old and new shadow " 140 "file names must begin with a /.\n")); 141 exit(1); 142 } 143 144 if (strlen(new_vol) > DSW_NAMELEN) { 145 (void) fprintf(stderr, 146 gettext("New shadow name is to long.\n")); 147 exit(1); 148 } 149 150 /* check old shadow is in dscfg */ 151 if (find_cfg_info(old_vol, SHADOW_TOKEN) == 0) { 152 (void) fprintf(stderr, 153 gettext("Old shadow not in existing cfg\n")); 154 exit(1); 155 } 156 157 /* check ii set status, suspend if need */ 158 (void) strncpy(args.shadow_vol, old_vol, DSW_NAMELEN); 159 args.shadow_vol[DSW_NAMELEN-1] = '\0'; 160 args.status = spcs_s_ucreate(); 161 if (ioctl(dsw_fd, DSWIOC_STAT, &args) != -1) { 162 (void) fprintf(stderr, gettext("Suspend the Point-in-Time Copy " 163 "set first\n")); 164 (void) close(dsw_fd); 165 exit(1); 166 } 167 168 if (copy_shadow) { 169 if (copy_shadow_vol(old_vol, new_vol) == 0) { 170 perror(gettext("Write new shadow failed")); 171 (void) close(dsw_fd); 172 exit(1); 173 } 174 } 175 if (find_cfg_info(old_vol, SV_TOKEN) == 0) { 176 (void) fprintf(stderr, 177 gettext("Old shadow not in existing cfg\n")); 178 exit(1); 179 } 180 if (find_cfg_info(old_vol, DSVOL_TOKEN) == 0) { 181 (void) fprintf(stderr, 182 gettext("Old shadow not in existing cfg\n")); 183 exit(1); 184 } 185 if (strstr(real_bitmap, "/rdsk/") == NULL) { 186 (void) fprintf(stderr, 187 gettext("%s is not a character device\n"), real_bitmap); 188 exit(1); 189 } 190 191 /* use block device /dsk/ to update bitmap header */ 192 convert_to_blockdevice(); 193 194 /* open bitmap by using update mode */ 195 if ((ifp = fopen(real_bitmap, "r+")) == NULL) { 196 (void) fprintf(stderr, gettext("Can't open bitmap file\n")); 197 exit(1); 198 } 199 200 /* Check old header looks like an II bitmap header */ 201 if (fread(&header, DSW_CBLK_FBA, FBA_SIZE(1), ifp) != FBA_SIZE(1)) { 202 (void) fprintf(stderr, gettext("Can't read bitmap file\n")); 203 exit(1); 204 } 205 206 if (hp->ii_magic != DSW_CLEAN && hp->ii_magic != DSW_DIRTY) { 207 (void) fprintf(stderr, 208 gettext("%s is not a Point-in-Time Copy " 209 "shadow.\n"), old_vol); 210 exit(1); 211 } 212 213 if (strncmp(hp->shadow_vol, old_vol, DSW_NAMELEN) != 0) { 214 (void) fprintf(stderr, gettext("%s has Point-in-Time Copy " 215 "shadow magic number,\n" 216 "but does not contain correct data.\n"), old_vol); 217 exit(1); 218 } 219 220 (void) memset(hp->shadow_vol, 0, DSW_NAMELEN); 221 (void) strncpy(hp->shadow_vol, new_vol, DSW_NAMELEN); 222 223 /* reset the pointer position */ 224 rewind(ifp); 225 if (fwrite(&header, DSW_CBLK_FBA, FBA_SIZE(1), ifp) != FBA_SIZE(1)) { 226 perror(new_vol); 227 (void) fprintf(stderr, 228 gettext("Can't write new bitmap header\n")); 229 exit(1); 230 } 231 (void) fclose(ifp); 232 (void) close(dsw_fd); 233 if (update_dscfg(new_vol) == 0) { 234 (void) fprintf(stderr, gettext("Failed to update dscfg.\n")); 235 exit(1); 236 } else { 237 spcs_log("ii", NULL, 238 "iicpshd copy shadow from %s to %s", 239 old_vol, new_vol); 240 } 241 } 242 243 /* 244 * find_cfg_info() 245 * 246 */ 247 248 int 249 find_cfg_info(char *volume, char *token) 250 { 251 int i; 252 /* get read lock */ 253 if (!cfg_lock(cfg, CFG_RDLOCK)) { 254 spcs_log("ii", NULL, 255 "iicpbmp CFG_RDLOCK failed, errno %d", errno); 256 (void) fprintf(stderr, gettext("Error locking config\n")); 257 exit(1); 258 } 259 for (i = 1; ; i++) { 260 bzero(buf, CFG_MAX_BUF); 261 (void) snprintf(key, sizeof (key), token, i); 262 if (cfg_get_cstring(cfg, key, buf, DSW_NAMELEN) < 0) { 263 cfg_unlock(cfg); 264 return (0); 265 } 266 if (strcmp(buf, volume) == 0) { 267 if (strcmp(token, SHADOW_TOKEN) == 0) { 268 (void) snprintf(key, sizeof (key), 269 BITMAP_TOKEN, i); 270 (void) cfg_get_cstring(cfg, key, 271 real_bitmap, DSW_NAMELEN); 272 set_number = i; 273 } else if (strcmp(token, SV_TOKEN) == 0) { 274 sv_number = i; 275 } else if (strcmp(token, DSVOL_TOKEN) == 0) { 276 dsvol_number = i; 277 } 278 /* release read lock */ 279 cfg_unlock(cfg); 280 return (1); 281 } 282 } 283 } 284 285 int 286 copy_shadow_vol(char *old_shadow, char *new_shadow) { 287 int i; 288 char cp_buffer[256]; 289 FILE *ishdfp, *oshdfp; 290 if ((ishdfp = fopen(old_shadow, "r")) == NULL) { 291 (void) fprintf(stderr, gettext("Can't open old shadow file\n")); 292 return (0); 293 } 294 if ((oshdfp = fopen(new_shadow, "w")) == NULL) { 295 (void) fprintf(stderr, gettext("Can't open new shadow file\n")); 296 return (0); 297 } 298 299 /* Copy the shadow vol */ 300 while ((i = fread(cp_buffer, sizeof (char), sizeof (cp_buffer), ishdfp)) 301 > 0) { 302 if (fwrite(cp_buffer, sizeof (char), i, oshdfp) != i) { 303 (void) fclose(ishdfp); 304 (void) fclose(oshdfp); 305 return (0); 306 } 307 } 308 (void) fclose(ishdfp); 309 (void) fclose(oshdfp); 310 return (1); 311 } 312 313 int 314 update_dscfg(char *new_shadow) { 315 316 int len = strlen(new_shadow); 317 /* get write lock */ 318 if (!cfg_lock(cfg, CFG_WRLOCK)) { 319 spcs_log("ii", NULL, 320 "iicpbmp CFG_WRLOCK failed, errno %d", errno); 321 (void) fprintf(stderr, gettext("Error locking config\n")); 322 return (0); 323 } 324 (void) sprintf(key, SHADOW_TOKEN, set_number); 325 if (cfg_put_cstring(cfg, key, new_shadow, len) < 0) { 326 perror("cfg_put_cstring"); 327 return (0); 328 } 329 (void) sprintf(key, SV_TOKEN, sv_number); 330 if (cfg_put_cstring(cfg, key, new_shadow, len) < 0) { 331 perror("cfg_put_cstring"); 332 return (0); 333 } 334 (void) sprintf(key, DSVOL_TOKEN, dsvol_number); 335 if (cfg_put_cstring(cfg, key, new_shadow, len) < 0) { 336 perror("cfg_put_cstring"); 337 return (0); 338 } 339 (void) cfg_commit(cfg); 340 cfg_unlock(cfg); 341 return (1); 342 } 343 344 void 345 convert_to_blockdevice() { 346 int len = strlen(real_bitmap); 347 int i = 0, j = 0; 348 char *temp_string = malloc(len-1); 349 while (i < len + 1) { 350 if (real_bitmap[i] != 'r') { 351 temp_string[j] = real_bitmap[i]; 352 j++; 353 } 354 i++; 355 } 356 (void) strcpy(real_bitmap, temp_string); 357 free(temp_string); 358 } 359