iicpbmp.c revision fcf3ce441efd61da9bb2884968af01cb7c1452cc
/*
* 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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <sys/types.h>
#include <sys/time.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <values.h>
#include <locale.h>
#include <sys/stat.h>
#include <strings.h>
#include <stdarg.h>
#include <sys/param.h>
#include <nsctl.h>
#include <sys/nsctl/cfg.h>
#include <sys/unistat/spcs_s.h>
#include <sys/unistat/spcs_s_u.h>
#include <sys/unistat/spcs_errors.h>
#include <sys/nsctl/dsw.h>
#include <sys/nsctl/dsw_dev.h>
#define DSW_TEXT_DOMAIN "II"
void iicpbmp_usage();
void copybmp(char *, char *);
int find_bitmap_cfg(char *);
extern int optind;
char *cmdnam;
extern char *optarg;
extern int optind, opterr, optopt;
int update_cfg = 1;
CFGFILE *cfg;
char shadow[DSW_NAMELEN];
char buf[CFG_MAX_BUF];
char key[CFG_MAX_KEY];
int setnumber;
#ifdef lint
int
iicpbmp_lintmain(int argc, char *argv[])
#else
int
main(int argc, char *argv[])
#endif
{
cmdnam = argv[0];
if (argc > 1) {
if (strcmp(argv[1], "-c") == 0) {
/* don't update cfg information */
update_cfg = 0;
argc--;
argv++;
}
}
if (argc == 1 || (argc%2) == 0) /* must have pairs of filenames */
iicpbmp_usage();
if (update_cfg) {
if ((cfg = cfg_open(NULL)) == NULL) {
fprintf(stderr, gettext("Error opening config\n"));
exit(1);
}
if (!cfg_lock(cfg, CFG_WRLOCK)) {
spcs_log("ii", NULL,
"iicpbmp CFG_WRLOCK failed, errno %d", errno);
fprintf(stderr, gettext("Error locking config\n"));
exit(1);
}
}
for (argv++; *argv != NULL; argv += 2)
copybmp(argv[0], argv[1]);
if (update_cfg)
cfg_close(cfg);
exit(0);
return (0);
}
void
iicpbmp_usage()
{
fprintf(stderr, gettext("Usage:\n"));
fprintf(stderr, gettext("\tiicpbmp [-c] old_bitmap new_bitmap\n"));
exit(1);
}
void
copybmp(char *old_bitmap, char *new_bitmap)
{
int i;
int dsw_fd;
FILE *ifp, *ofp;
ii_header_t header;
char cp_buffer[256];
dsw_stat_t args;
dsw_fd = open(DSWDEV, O_RDONLY);
if (dsw_fd < 0) {
perror(DSWDEV);
exit(1);
}
if (*old_bitmap != '/' || *new_bitmap != '/') {
fprintf(stderr, gettext(
"Both old and new bitmap file names must begin with a /.\n"));
exit(1);
}
if (strlen(new_bitmap) > DSW_NAMELEN) {
fprintf(stderr, gettext("New bitmap name is to long.\n"));
exit(1);
}
if (update_cfg && find_bitmap_cfg(old_bitmap) == 0) {
perror(old_bitmap);
fprintf(stderr, gettext("Old bitmap not in existing cfg\n"));
exit(1);
}
strncpy(args.shadow_vol, shadow, DSW_NAMELEN);
args.shadow_vol[DSW_NAMELEN-1] = '\0';
args.status = spcs_s_ucreate();
if (ioctl(dsw_fd, DSWIOC_STAT, &args) != -1) {
fprintf(stderr, gettext("Suspend the Point-in-Time Copy "
"set first\n"));
close(dsw_fd);
exit(1);
}
if ((ifp = fopen(old_bitmap, "r")) == NULL) {
perror(old_bitmap);
fprintf(stderr, gettext("Can't open old bitmap file\n"));
exit(1);
}
/* Check old header looks like an Point-in-Time Copy bitmap header */
if (fread(&header, sizeof (header), 1, ifp) != 1) {
fprintf(stderr, gettext("Can't read old bitmap file\n"));
exit(1);
}
if (header.ii_magic != DSW_CLEAN && header.ii_magic != DSW_DIRTY) {
fprintf(stderr, gettext("%s is not a Point-in-Time Copy "
"bitmap.\n"), old_bitmap);
exit(1);
}
if (strncmp(header.bitmap_vol, old_bitmap, DSW_NAMELEN) != 0) {
fprintf(stderr, gettext(
"%s has Point-in-Time Copy bitmap magic number,\n"
"but does not contain correct data.\n"), old_bitmap);
exit(1);
}
if ((ofp = fopen(new_bitmap, "w")) == NULL) {
perror(new_bitmap);
fprintf(stderr, gettext("Can't open new bitmap file\n"));
exit(1);
}
/* Set up new header */
memset(header.bitmap_vol, 0, DSW_NAMELEN);
strncpy(header.bitmap_vol, new_bitmap, DSW_NAMELEN);
if (fwrite(&header, sizeof (header), 1, ofp) != 1) {
perror(new_bitmap);
fprintf(stderr, gettext("Can't write new bitmap header\n"));
exit(1);
}
/* Copy the bitmap itself */
while ((i = fread(cp_buffer, sizeof (char), sizeof (cp_buffer), ifp))
> 0) {
if (fwrite(cp_buffer, sizeof (char), i, ofp) != i) {
perror(gettext("Write new bitmap failed"));
break;
}
}
fclose(ofp);
fclose(ifp);
close(dsw_fd);
if (update_cfg) {
sprintf(key, "ii.set%d.bitmap", setnumber);
if (cfg_put_cstring(cfg, key, new_bitmap, strlen(new_bitmap))
< 0) {
perror("cfg_put_cstring");
}
cfg_commit(cfg);
spcs_log("ii", NULL,
"iicpbmp copy bit map for %s from %s to %s",
shadow, old_bitmap, new_bitmap);
}
}
/*
* find_bitmap_cfg()
*
*/
int
find_bitmap_cfg(char *bitmap)
{
for (setnumber = 1; ; setnumber++) {
bzero(buf, CFG_MAX_BUF);
snprintf(key, sizeof (key), "ii.set%d.bitmap", setnumber);
if (cfg_get_cstring(cfg, key, buf, DSW_NAMELEN) < 0)
return (0);
if (strcmp(buf, bitmap) == 0) {
snprintf(key, sizeof (key), "ii.set%d.shadow",
setnumber);
cfg_get_cstring(cfg, key, shadow, DSW_NAMELEN);
return (setnumber);
}
}
}