17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*342440ecSPrasad Singamsetty * Common Development and Distribution License (the "License"). 6*342440ecSPrasad Singamsetty * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21*342440ecSPrasad Singamsetty 227c478bd9Sstevel@tonic-gate /* 23*342440ecSPrasad Singamsetty * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /*LINTLIBRARY*/ 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <stdio.h> 317c478bd9Sstevel@tonic-gate #include <errno.h> 327c478bd9Sstevel@tonic-gate #include <memory.h> 337c478bd9Sstevel@tonic-gate #include <unistd.h> 347c478bd9Sstevel@tonic-gate #include <sys/types.h> 357c478bd9Sstevel@tonic-gate #include <sys/param.h> 367c478bd9Sstevel@tonic-gate #include <sys/dkio.h> 377c478bd9Sstevel@tonic-gate #include <sys/vtoc.h> 38*342440ecSPrasad Singamsetty #include <strings.h> 39*342440ecSPrasad Singamsetty #include <limits.h> 40*342440ecSPrasad Singamsetty 41*342440ecSPrasad Singamsetty /* 42*342440ecSPrasad Singamsetty * To copy each field of vtoc individually for copying extvtoc 43*342440ecSPrasad Singamsetty * to 32 bit vtoc and vs. 44*342440ecSPrasad Singamsetty * Currently bootinfo and timestamp are not really supported. 45*342440ecSPrasad Singamsetty */ 46*342440ecSPrasad Singamsetty 47*342440ecSPrasad Singamsetty #define libadm_vtoc_copy(vs, vd) \ 48*342440ecSPrasad Singamsetty { \ 49*342440ecSPrasad Singamsetty int i; \ 50*342440ecSPrasad Singamsetty vd->v_bootinfo[0] = (unsigned)vs->v_bootinfo[0]; \ 51*342440ecSPrasad Singamsetty vd->v_bootinfo[1] = (unsigned)vs->v_bootinfo[1]; \ 52*342440ecSPrasad Singamsetty vd->v_bootinfo[2] = (unsigned)vs->v_bootinfo[2]; \ 53*342440ecSPrasad Singamsetty vd->v_sanity = (unsigned)vs->v_sanity; \ 54*342440ecSPrasad Singamsetty vd->v_version = (unsigned)vs->v_version; \ 55*342440ecSPrasad Singamsetty bcopy(vs->v_volume, vd->v_volume, LEN_DKL_VVOL); \ 56*342440ecSPrasad Singamsetty vd->v_sectorsz = vs->v_sectorsz; \ 57*342440ecSPrasad Singamsetty vd->v_nparts = vs->v_nparts; \ 58*342440ecSPrasad Singamsetty vd->v_version = (unsigned)vs->v_version; \ 59*342440ecSPrasad Singamsetty for (i = 0; i < 10; i++) \ 60*342440ecSPrasad Singamsetty vd->v_reserved[i] = (unsigned)vs->v_reserved[i];\ 61*342440ecSPrasad Singamsetty for (i = 0; i < V_NUMPAR; i++) { \ 62*342440ecSPrasad Singamsetty vd->v_part[i].p_tag = vs->v_part[i].p_tag; \ 63*342440ecSPrasad Singamsetty vd->v_part[i].p_flag = vs->v_part[i].p_flag; \ 64*342440ecSPrasad Singamsetty vd->v_part[i].p_start = (unsigned)vs->v_part[i].p_start;\ 65*342440ecSPrasad Singamsetty vd->v_part[i].p_size = (unsigned)vs->v_part[i].p_size; \ 66*342440ecSPrasad Singamsetty } \ 67*342440ecSPrasad Singamsetty for (i = 0; i < V_NUMPAR; i++) \ 68*342440ecSPrasad Singamsetty if ((sizeof (vd->timestamp[i]) != sizeof (vs->timestamp[i])) &&\ 69*342440ecSPrasad Singamsetty (vs->timestamp[i] > INT32_MAX)) \ 70*342440ecSPrasad Singamsetty vd->timestamp[i] = INT32_MAX; \ 71*342440ecSPrasad Singamsetty else \ 72*342440ecSPrasad Singamsetty vd->timestamp[i] = (unsigned)vs->timestamp[i]; \ 73*342440ecSPrasad Singamsetty bcopy(vs->v_asciilabel, vd->v_asciilabel, LEN_DKL_ASCII); \ 74*342440ecSPrasad Singamsetty } 75*342440ecSPrasad Singamsetty 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate /* 787c478bd9Sstevel@tonic-gate * Read VTOC - return partition number. 797c478bd9Sstevel@tonic-gate */ 807c478bd9Sstevel@tonic-gate int 817c478bd9Sstevel@tonic-gate read_vtoc(int fd, struct vtoc *vtoc) 827c478bd9Sstevel@tonic-gate { 837c478bd9Sstevel@tonic-gate struct dk_cinfo dki_info; 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate /* 867c478bd9Sstevel@tonic-gate * Read the vtoc. 877c478bd9Sstevel@tonic-gate */ 887c478bd9Sstevel@tonic-gate if (ioctl(fd, DKIOCGVTOC, (caddr_t)vtoc) == -1) { 897c478bd9Sstevel@tonic-gate switch (errno) { 907c478bd9Sstevel@tonic-gate case EIO: 917c478bd9Sstevel@tonic-gate return (VT_EIO); 927c478bd9Sstevel@tonic-gate case EINVAL: 937c478bd9Sstevel@tonic-gate return (VT_EINVAL); 947c478bd9Sstevel@tonic-gate case ENOTSUP: 95*342440ecSPrasad Singamsetty /* GPT labeled or disk > 1TB with no extvtoc support */ 967c478bd9Sstevel@tonic-gate return (VT_ENOTSUP); 97*342440ecSPrasad Singamsetty case EOVERFLOW: 98*342440ecSPrasad Singamsetty return (VT_EOVERFLOW); 997c478bd9Sstevel@tonic-gate default: 1007c478bd9Sstevel@tonic-gate return (VT_ERROR); 1017c478bd9Sstevel@tonic-gate } 1027c478bd9Sstevel@tonic-gate } 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate /* 1057c478bd9Sstevel@tonic-gate * Sanity-check the vtoc. 1067c478bd9Sstevel@tonic-gate */ 1077c478bd9Sstevel@tonic-gate if (vtoc->v_sanity != VTOC_SANE) { 1087c478bd9Sstevel@tonic-gate return (VT_EINVAL); 1097c478bd9Sstevel@tonic-gate } 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate /* 1127c478bd9Sstevel@tonic-gate * Convert older-style vtoc's. 1137c478bd9Sstevel@tonic-gate */ 1147c478bd9Sstevel@tonic-gate switch (vtoc->v_version) { 1157c478bd9Sstevel@tonic-gate case 0: 1167c478bd9Sstevel@tonic-gate /* 1177c478bd9Sstevel@tonic-gate * No vtoc information. Install default 1187c478bd9Sstevel@tonic-gate * nparts/sectorsz and version. We are 1197c478bd9Sstevel@tonic-gate * assuming that the driver returns the 1207c478bd9Sstevel@tonic-gate * current partition information correctly. 1217c478bd9Sstevel@tonic-gate */ 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate vtoc->v_version = V_VERSION; 1247c478bd9Sstevel@tonic-gate if (vtoc->v_nparts == 0) 1257c478bd9Sstevel@tonic-gate vtoc->v_nparts = V_NUMPAR; 1267c478bd9Sstevel@tonic-gate if (vtoc->v_sectorsz == 0) 1277c478bd9Sstevel@tonic-gate vtoc->v_sectorsz = DEV_BSIZE; 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate break; 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate case V_VERSION: 1327c478bd9Sstevel@tonic-gate break; 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate default: 1357c478bd9Sstevel@tonic-gate return (VT_EINVAL); 1367c478bd9Sstevel@tonic-gate } 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate /* 1397c478bd9Sstevel@tonic-gate * Return partition number for this file descriptor. 1407c478bd9Sstevel@tonic-gate */ 1417c478bd9Sstevel@tonic-gate if (ioctl(fd, DKIOCINFO, (caddr_t)&dki_info) == -1) { 1427c478bd9Sstevel@tonic-gate switch (errno) { 1437c478bd9Sstevel@tonic-gate case EIO: 1447c478bd9Sstevel@tonic-gate return (VT_EIO); 1457c478bd9Sstevel@tonic-gate case EINVAL: 1467c478bd9Sstevel@tonic-gate return (VT_EINVAL); 1477c478bd9Sstevel@tonic-gate default: 1487c478bd9Sstevel@tonic-gate return (VT_ERROR); 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate if (dki_info.dki_partition > V_NUMPAR) { 1527c478bd9Sstevel@tonic-gate return (VT_EINVAL); 1537c478bd9Sstevel@tonic-gate } 1547c478bd9Sstevel@tonic-gate return ((int)dki_info.dki_partition); 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate /* 1587c478bd9Sstevel@tonic-gate * Write VTOC 1597c478bd9Sstevel@tonic-gate */ 1607c478bd9Sstevel@tonic-gate int 1617c478bd9Sstevel@tonic-gate write_vtoc(int fd, struct vtoc *vtoc) 1627c478bd9Sstevel@tonic-gate { 1637c478bd9Sstevel@tonic-gate int i; 1647c478bd9Sstevel@tonic-gate /* 1657c478bd9Sstevel@tonic-gate * Sanity-check the vtoc 1667c478bd9Sstevel@tonic-gate */ 1677c478bd9Sstevel@tonic-gate if (vtoc->v_sanity != VTOC_SANE || vtoc->v_nparts > V_NUMPAR) { 1687c478bd9Sstevel@tonic-gate return (-1); 1697c478bd9Sstevel@tonic-gate } 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate /* 1727c478bd9Sstevel@tonic-gate * since many drivers won't allow opening a device make sure 1737c478bd9Sstevel@tonic-gate * all partitions aren't being set to zero. If all are zero then 1747c478bd9Sstevel@tonic-gate * we have no way to set them to something else 1757c478bd9Sstevel@tonic-gate */ 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate for (i = 0; i < (int)vtoc->v_nparts; i++) 1787c478bd9Sstevel@tonic-gate if (vtoc->v_part[i].p_size > 0) 1797c478bd9Sstevel@tonic-gate break; 1807c478bd9Sstevel@tonic-gate if (i == (int)vtoc->v_nparts) 1817c478bd9Sstevel@tonic-gate return (-1); 1827c478bd9Sstevel@tonic-gate 1837c478bd9Sstevel@tonic-gate /* 1847c478bd9Sstevel@tonic-gate * Write the vtoc 1857c478bd9Sstevel@tonic-gate */ 1867c478bd9Sstevel@tonic-gate if (ioctl(fd, DKIOCSVTOC, (caddr_t)vtoc) == -1) { 1877c478bd9Sstevel@tonic-gate switch (errno) { 1887c478bd9Sstevel@tonic-gate case EIO: 1897c478bd9Sstevel@tonic-gate return (VT_EIO); 1907c478bd9Sstevel@tonic-gate case EINVAL: 1917c478bd9Sstevel@tonic-gate return (VT_EINVAL); 1927c478bd9Sstevel@tonic-gate case ENOTSUP: 193*342440ecSPrasad Singamsetty /* GPT labeled or disk > 1TB with no extvtoc support */ 1947c478bd9Sstevel@tonic-gate return (VT_ENOTSUP); 195*342440ecSPrasad Singamsetty case EOVERFLOW: 196*342440ecSPrasad Singamsetty return (VT_EOVERFLOW); 1977c478bd9Sstevel@tonic-gate default: 1987c478bd9Sstevel@tonic-gate return (VT_ERROR); 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate } 2017c478bd9Sstevel@tonic-gate return (0); 2027c478bd9Sstevel@tonic-gate } 203*342440ecSPrasad Singamsetty 204*342440ecSPrasad Singamsetty int 205*342440ecSPrasad Singamsetty read_extvtoc(int fd, struct extvtoc *extvtoc) 206*342440ecSPrasad Singamsetty { 207*342440ecSPrasad Singamsetty struct dk_cinfo dki_info; 208*342440ecSPrasad Singamsetty struct vtoc oldvtoc; 209*342440ecSPrasad Singamsetty struct vtoc *oldvtocp = &oldvtoc; 210*342440ecSPrasad Singamsetty int ret; 211*342440ecSPrasad Singamsetty 212*342440ecSPrasad Singamsetty /* 213*342440ecSPrasad Singamsetty * Read the vtoc. 214*342440ecSPrasad Singamsetty */ 215*342440ecSPrasad Singamsetty if (ioctl(fd, DKIOCGEXTVTOC, (caddr_t)extvtoc) == -1) { 216*342440ecSPrasad Singamsetty switch (errno) { 217*342440ecSPrasad Singamsetty case EIO: 218*342440ecSPrasad Singamsetty return (VT_EIO); 219*342440ecSPrasad Singamsetty case EINVAL: 220*342440ecSPrasad Singamsetty return (VT_EINVAL); 221*342440ecSPrasad Singamsetty /* for disks > 1TB */ 222*342440ecSPrasad Singamsetty case ENOTSUP: 223*342440ecSPrasad Singamsetty return (VT_ENOTSUP); 224*342440ecSPrasad Singamsetty case EOVERFLOW: 225*342440ecSPrasad Singamsetty return (VT_EOVERFLOW); 226*342440ecSPrasad Singamsetty case ENOTTY: 227*342440ecSPrasad Singamsetty 228*342440ecSPrasad Singamsetty if ((ret = read_vtoc(fd, oldvtocp)) < 0) 229*342440ecSPrasad Singamsetty return (ret); 230*342440ecSPrasad Singamsetty 231*342440ecSPrasad Singamsetty #ifdef _LP64 232*342440ecSPrasad Singamsetty /* 233*342440ecSPrasad Singamsetty * 64-bit vtoc and extvtoc have the same field sizes 234*342440ecSPrasad Singamsetty * and offsets. 235*342440ecSPrasad Singamsetty */ 236*342440ecSPrasad Singamsetty bcopy(oldvtocp, extvtoc, sizeof (struct extvtoc)); 237*342440ecSPrasad Singamsetty #else 238*342440ecSPrasad Singamsetty bzero(extvtoc, sizeof (struct extvtoc)); 239*342440ecSPrasad Singamsetty libadm_vtoc_copy(oldvtocp, extvtoc); 240*342440ecSPrasad Singamsetty #endif 241*342440ecSPrasad Singamsetty return (ret); 242*342440ecSPrasad Singamsetty 243*342440ecSPrasad Singamsetty 244*342440ecSPrasad Singamsetty default: 245*342440ecSPrasad Singamsetty return (VT_ERROR); 246*342440ecSPrasad Singamsetty } 247*342440ecSPrasad Singamsetty } 248*342440ecSPrasad Singamsetty 249*342440ecSPrasad Singamsetty /* 250*342440ecSPrasad Singamsetty * Sanity-check the vtoc. 251*342440ecSPrasad Singamsetty */ 252*342440ecSPrasad Singamsetty if (extvtoc->v_sanity != VTOC_SANE) { 253*342440ecSPrasad Singamsetty return (VT_EINVAL); 254*342440ecSPrasad Singamsetty } 255*342440ecSPrasad Singamsetty 256*342440ecSPrasad Singamsetty switch (extvtoc->v_version) { 257*342440ecSPrasad Singamsetty case 0: 258*342440ecSPrasad Singamsetty /* 259*342440ecSPrasad Singamsetty * For pre-version 1 vtoc keep same functionality 260*342440ecSPrasad Singamsetty * as read_vtoc. 261*342440ecSPrasad Singamsetty */ 262*342440ecSPrasad Singamsetty 263*342440ecSPrasad Singamsetty extvtoc->v_version = V_VERSION; 264*342440ecSPrasad Singamsetty if (extvtoc->v_nparts == 0) 265*342440ecSPrasad Singamsetty extvtoc->v_nparts = V_NUMPAR; 266*342440ecSPrasad Singamsetty if (extvtoc->v_sectorsz == 0) 267*342440ecSPrasad Singamsetty extvtoc->v_sectorsz = DEV_BSIZE; 268*342440ecSPrasad Singamsetty 269*342440ecSPrasad Singamsetty break; 270*342440ecSPrasad Singamsetty 271*342440ecSPrasad Singamsetty case V_VERSION: 272*342440ecSPrasad Singamsetty break; 273*342440ecSPrasad Singamsetty 274*342440ecSPrasad Singamsetty default: 275*342440ecSPrasad Singamsetty return (VT_EINVAL); 276*342440ecSPrasad Singamsetty } 277*342440ecSPrasad Singamsetty 278*342440ecSPrasad Singamsetty /* 279*342440ecSPrasad Singamsetty * Return partition number for this file descriptor. 280*342440ecSPrasad Singamsetty */ 281*342440ecSPrasad Singamsetty if (ioctl(fd, DKIOCINFO, (caddr_t)&dki_info) == -1) { 282*342440ecSPrasad Singamsetty switch (errno) { 283*342440ecSPrasad Singamsetty case EIO: 284*342440ecSPrasad Singamsetty return (VT_EIO); 285*342440ecSPrasad Singamsetty case EINVAL: 286*342440ecSPrasad Singamsetty return (VT_EINVAL); 287*342440ecSPrasad Singamsetty default: 288*342440ecSPrasad Singamsetty return (VT_ERROR); 289*342440ecSPrasad Singamsetty } 290*342440ecSPrasad Singamsetty } 291*342440ecSPrasad Singamsetty if (dki_info.dki_partition > V_NUMPAR) { 292*342440ecSPrasad Singamsetty return (VT_EINVAL); 293*342440ecSPrasad Singamsetty } 294*342440ecSPrasad Singamsetty return ((int)dki_info.dki_partition); 295*342440ecSPrasad Singamsetty } 296*342440ecSPrasad Singamsetty 297*342440ecSPrasad Singamsetty /* 298*342440ecSPrasad Singamsetty * Write ext VTOC. 299*342440ecSPrasad Singamsetty */ 300*342440ecSPrasad Singamsetty int 301*342440ecSPrasad Singamsetty write_extvtoc(int fd, struct extvtoc *extvtoc) 302*342440ecSPrasad Singamsetty { 303*342440ecSPrasad Singamsetty int i; 304*342440ecSPrasad Singamsetty struct vtoc oldvtoc; 305*342440ecSPrasad Singamsetty struct vtoc *oldvtocp = &oldvtoc; 306*342440ecSPrasad Singamsetty /* 307*342440ecSPrasad Singamsetty * Sanity-check the vtoc 308*342440ecSPrasad Singamsetty */ 309*342440ecSPrasad Singamsetty if (extvtoc->v_sanity != VTOC_SANE || extvtoc->v_nparts > V_NUMPAR) { 310*342440ecSPrasad Singamsetty return (-1); 311*342440ecSPrasad Singamsetty } 312*342440ecSPrasad Singamsetty 313*342440ecSPrasad Singamsetty /* 314*342440ecSPrasad Singamsetty * since many drivers won't allow opening a device make sure 315*342440ecSPrasad Singamsetty * all partitions aren't being set to zero. If all are zero then 316*342440ecSPrasad Singamsetty * we have no way to set them to something else 317*342440ecSPrasad Singamsetty */ 318*342440ecSPrasad Singamsetty 319*342440ecSPrasad Singamsetty for (i = 0; i < (int)extvtoc->v_nparts; i++) 320*342440ecSPrasad Singamsetty if (extvtoc->v_part[i].p_size > 0) 321*342440ecSPrasad Singamsetty break; 322*342440ecSPrasad Singamsetty if (i == (int)extvtoc->v_nparts) 323*342440ecSPrasad Singamsetty return (-1); 324*342440ecSPrasad Singamsetty 325*342440ecSPrasad Singamsetty /* 326*342440ecSPrasad Singamsetty * Write the extvtoc 327*342440ecSPrasad Singamsetty */ 328*342440ecSPrasad Singamsetty if (ioctl(fd, DKIOCSEXTVTOC, (caddr_t)extvtoc) == -1) { 329*342440ecSPrasad Singamsetty switch (errno) { 330*342440ecSPrasad Singamsetty case EIO: 331*342440ecSPrasad Singamsetty return (VT_EIO); 332*342440ecSPrasad Singamsetty case EINVAL: 333*342440ecSPrasad Singamsetty return (VT_EINVAL); 334*342440ecSPrasad Singamsetty /* for disks > 1TB */ 335*342440ecSPrasad Singamsetty case ENOTSUP: 336*342440ecSPrasad Singamsetty return (VT_ENOTSUP); 337*342440ecSPrasad Singamsetty case EOVERFLOW: 338*342440ecSPrasad Singamsetty return (VT_EOVERFLOW); 339*342440ecSPrasad Singamsetty case ENOTTY: 340*342440ecSPrasad Singamsetty #ifdef _LP64 341*342440ecSPrasad Singamsetty /* 342*342440ecSPrasad Singamsetty * 64-bit vtoc and extvtoc have the same field sizes 343*342440ecSPrasad Singamsetty * and offsets. 344*342440ecSPrasad Singamsetty */ 345*342440ecSPrasad Singamsetty bcopy(extvtoc, oldvtocp, sizeof (struct vtoc)); 346*342440ecSPrasad Singamsetty #else 347*342440ecSPrasad Singamsetty bzero(oldvtocp, sizeof (struct vtoc)); 348*342440ecSPrasad Singamsetty libadm_vtoc_copy(extvtoc, oldvtocp); 349*342440ecSPrasad Singamsetty 350*342440ecSPrasad Singamsetty #endif 351*342440ecSPrasad Singamsetty return (write_vtoc(fd, &oldvtoc)); 352*342440ecSPrasad Singamsetty 353*342440ecSPrasad Singamsetty default: 354*342440ecSPrasad Singamsetty return (VT_ERROR); 355*342440ecSPrasad Singamsetty } 356*342440ecSPrasad Singamsetty } 357*342440ecSPrasad Singamsetty 358*342440ecSPrasad Singamsetty return (0); 359*342440ecSPrasad Singamsetty } 360