/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* for bitmap format */ #define DSW_TEXT_DOMAIN "II" #define BITMAP_TOKEN "ii.set%d.bitmap" #define SHADOW_TOKEN "ii.set%d.shadow" #define SV_TOKEN "sv.set%d.vol" #define DSVOL_TOKEN "dsvol.set%d.path" void iicpshd_usage(); void copyshd(char *, char *); int find_cfg_info(char *, char *); int copy_shadow_vol(char *, char *); void convert_to_blockdevice(); int update_dscfg(char *); extern int optind; extern char *optarg; extern int optind, opterr, optopt; int copy_shadow = 1; CFGFILE *cfg; char real_bitmap[DSW_NAMELEN]; char buf[CFG_MAX_BUF]; char key[CFG_MAX_KEY]; int set_number; int sv_number; int dsvol_number; #ifdef lint int iicpshd_lintmain(int argc, char *argv[]) #else int main(int argc, char *argv[]) #endif { if (argc > 1) { if (strcmp(argv[1], "-s") == 0) { /* don't copy shadow, only update dscfg and ii header */ copy_shadow = 0; argc--; argv++; } } if (argc == 1 || (argc%2) == 0) /* must have pairs of filenames */ iicpshd_usage(); /* open dscfg anyway */ if ((cfg = cfg_open(NULL)) == NULL) { (void) fprintf(stderr, gettext("Error opening config\n")); exit(1); } for (argv++; *argv != NULL; argv += 2) copyshd(argv[0], argv[1]); /* close dscfg */ cfg_close(cfg); exit(0); return (0); } void iicpshd_usage() { (void) fprintf(stderr, gettext("Usage:\n")); (void) fprintf(stderr, gettext("\tiicpshd [-s] old_shadow new_shadow\n")); exit(1); } void copyshd(char *old_vol, char *new_vol) { int dsw_fd; FILE *ifp; char header[FBA_SIZE(1) * DSW_CBLK_FBA]; ii_header_t *hp; dsw_stat_t args; /*LINTED pointer alignment*/ hp = (ii_header_t *)&header; dsw_fd = open(DSWDEV, O_RDONLY); if (dsw_fd < 0) { perror(DSWDEV); exit(1); } if (*old_vol != '/' || *new_vol != '/') { (void) fprintf(stderr, gettext("Both old and new shadow " "file names must begin with a /.\n")); exit(1); } if (strlen(new_vol) > DSW_NAMELEN) { (void) fprintf(stderr, gettext("New shadow name is to long.\n")); exit(1); } /* check old shadow is in dscfg */ if (find_cfg_info(old_vol, SHADOW_TOKEN) == 0) { (void) fprintf(stderr, gettext("Old shadow not in existing cfg\n")); exit(1); } /* check ii set status, suspend if need */ (void) strncpy(args.shadow_vol, old_vol, DSW_NAMELEN); args.shadow_vol[DSW_NAMELEN-1] = '\0'; args.status = spcs_s_ucreate(); if (ioctl(dsw_fd, DSWIOC_STAT, &args) != -1) { (void) fprintf(stderr, gettext("Suspend the Point-in-Time Copy " "set first\n")); (void) close(dsw_fd); exit(1); } if (copy_shadow) { if (copy_shadow_vol(old_vol, new_vol) == 0) { perror(gettext("Write new shadow failed")); (void) close(dsw_fd); exit(1); } } if (find_cfg_info(old_vol, SV_TOKEN) == 0) { (void) fprintf(stderr, gettext("Old shadow not in existing cfg\n")); exit(1); } if (find_cfg_info(old_vol, DSVOL_TOKEN) == 0) { (void) fprintf(stderr, gettext("Old shadow not in existing cfg\n")); exit(1); } if (strstr(real_bitmap, "/rdsk/") == NULL) { (void) fprintf(stderr, gettext("%s is not a character device\n"), real_bitmap); exit(1); } /* use block device /dsk/ to update bitmap header */ convert_to_blockdevice(); /* open bitmap by using update mode */ if ((ifp = fopen(real_bitmap, "r+")) == NULL) { (void) fprintf(stderr, gettext("Can't open bitmap file\n")); exit(1); } /* Check old header looks like an II bitmap header */ if (fread(&header, DSW_CBLK_FBA, FBA_SIZE(1), ifp) != FBA_SIZE(1)) { (void) fprintf(stderr, gettext("Can't read bitmap file\n")); exit(1); } if (hp->ii_magic != DSW_CLEAN && hp->ii_magic != DSW_DIRTY) { (void) fprintf(stderr, gettext("%s is not a Point-in-Time Copy " "shadow.\n"), old_vol); exit(1); } if (strncmp(hp->shadow_vol, old_vol, DSW_NAMELEN) != 0) { (void) fprintf(stderr, gettext("%s has Point-in-Time Copy " "shadow magic number,\n" "but does not contain correct data.\n"), old_vol); exit(1); } (void) memset(hp->shadow_vol, 0, DSW_NAMELEN); (void) strncpy(hp->shadow_vol, new_vol, DSW_NAMELEN); /* reset the pointer position */ rewind(ifp); if (fwrite(&header, DSW_CBLK_FBA, FBA_SIZE(1), ifp) != FBA_SIZE(1)) { perror(new_vol); (void) fprintf(stderr, gettext("Can't write new bitmap header\n")); exit(1); } (void) fclose(ifp); (void) close(dsw_fd); if (update_dscfg(new_vol) == 0) { (void) fprintf(stderr, gettext("Failed to update dscfg.\n")); exit(1); } else { spcs_log("ii", NULL, "iicpshd copy shadow from %s to %s", old_vol, new_vol); } } /* * find_cfg_info() * */ int find_cfg_info(char *volume, char *token) { int i; /* get read lock */ if (!cfg_lock(cfg, CFG_RDLOCK)) { spcs_log("ii", NULL, "iicpbmp CFG_RDLOCK failed, errno %d", errno); (void) fprintf(stderr, gettext("Error locking config\n")); exit(1); } for (i = 1; ; i++) { bzero(buf, CFG_MAX_BUF); (void) snprintf(key, sizeof (key), token, i); if (cfg_get_cstring(cfg, key, buf, DSW_NAMELEN) < 0) { cfg_unlock(cfg); return (0); } if (strcmp(buf, volume) == 0) { if (strcmp(token, SHADOW_TOKEN) == 0) { (void) snprintf(key, sizeof (key), BITMAP_TOKEN, i); (void) cfg_get_cstring(cfg, key, real_bitmap, DSW_NAMELEN); set_number = i; } else if (strcmp(token, SV_TOKEN) == 0) { sv_number = i; } else if (strcmp(token, DSVOL_TOKEN) == 0) { dsvol_number = i; } /* release read lock */ cfg_unlock(cfg); return (1); } } } int copy_shadow_vol(char *old_shadow, char *new_shadow) { int i; char cp_buffer[256]; FILE *ishdfp, *oshdfp; if ((ishdfp = fopen(old_shadow, "r")) == NULL) { (void) fprintf(stderr, gettext("Can't open old shadow file\n")); return (0); } if ((oshdfp = fopen(new_shadow, "w")) == NULL) { (void) fprintf(stderr, gettext("Can't open new shadow file\n")); return (0); } /* Copy the shadow vol */ while ((i = fread(cp_buffer, sizeof (char), sizeof (cp_buffer), ishdfp)) > 0) { if (fwrite(cp_buffer, sizeof (char), i, oshdfp) != i) { (void) fclose(ishdfp); (void) fclose(oshdfp); return (0); } } (void) fclose(ishdfp); (void) fclose(oshdfp); return (1); } int update_dscfg(char *new_shadow) { int len = strlen(new_shadow); /* get write lock */ if (!cfg_lock(cfg, CFG_WRLOCK)) { spcs_log("ii", NULL, "iicpbmp CFG_WRLOCK failed, errno %d", errno); (void) fprintf(stderr, gettext("Error locking config\n")); return (0); } (void) sprintf(key, SHADOW_TOKEN, set_number); if (cfg_put_cstring(cfg, key, new_shadow, len) < 0) { perror("cfg_put_cstring"); return (0); } (void) sprintf(key, SV_TOKEN, sv_number); if (cfg_put_cstring(cfg, key, new_shadow, len) < 0) { perror("cfg_put_cstring"); return (0); } (void) sprintf(key, DSVOL_TOKEN, dsvol_number); if (cfg_put_cstring(cfg, key, new_shadow, len) < 0) { perror("cfg_put_cstring"); return (0); } (void) cfg_commit(cfg); cfg_unlock(cfg); return (1); } void convert_to_blockdevice() { int len = strlen(real_bitmap); int i = 0, j = 0; char *temp_string = malloc(len-1); while (i < len + 1) { if (real_bitmap[i] != 'r') { temp_string[j] = real_bitmap[i]; j++; } i++; } (void) strcpy(real_bitmap, temp_string); free(temp_string); }