1 /* 2 * File rock.c - generate RRIP records for iso9660 filesystems. 3 4 Written by Eric Youngdale (1993). 5 6 Copyright 1993 Yggdrasil Computing, Incorporated 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2, or (at your option) 11 any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ 21 22 #include <stdlib.h> 23 24 #include "config.h" 25 26 #ifndef VMS 27 #if defined(MAJOR_IN_SYSMACROS) 28 #include <sys/sysmacros.h> 29 #endif 30 31 #ifdef HAVE_UNISTD_H 32 #include <unistd.h> 33 #endif 34 35 #endif 36 #if defined(MAJOR_IN_MKDEV) 37 #include <sys/types.h> 38 #include <sys/mkdev.h> 39 #endif 40 41 #include "mkisofs.h" 42 #include "iso9660.h" 43 #include <string.h> 44 45 #ifdef DOESNT_WORK 46 47 #ifdef NON_UNIXFS 48 #define S_ISLNK(m) (0) 49 #else 50 #ifndef S_ISLNK 51 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) 52 #endif 53 #endif 54 55 #else 56 #include <statdefs.h> 57 #endif 58 59 #define SU_VERSION 1 60 61 #define SL_ROOT 8 62 #define SL_PARENT 4 63 #define SL_CURRENT 2 64 #define SL_CONTINUE 1 65 66 #define CE_SIZE 28 67 #define CL_SIZE 12 68 #define ER_SIZE 8 69 #define NM_SIZE 5 70 #define PL_SIZE 12 71 #define PN_SIZE 20 72 #define PX_SIZE 36 73 #define RE_SIZE 4 74 #define SL_SIZE 20 75 #define ZZ_SIZE 15 76 #ifdef APPLE_HYB 77 #define AA_SIZE 14 /* size of Apple extension */ 78 #endif /* APPLE_HYB */ 79 #ifdef __QNX__ 80 #define TF_SIZE (5 + 4 * 7) 81 #else 82 #define TF_SIZE (5 + 3 * 7) 83 #endif 84 85 /* If we need to store this number of bytes, make sure we 86 do not box ourselves in so that we do not have room for 87 a CE entry for the continuation record */ 88 89 #define MAYBE_ADD_CE_ENTRY(BYTES) \ 90 (BYTES + CE_SIZE + currlen + (ipnt - recstart) > reclimit ? 1 : 0) 91 92 /* 93 * Buffer to build RR attributes 94 */ 95 96 static unsigned char Rock[16384]; 97 static unsigned char symlink_buff[256]; 98 static int ipnt = 0; 99 static int recstart = 0; 100 static int currlen = 0; 101 static int mainrec = 0; 102 static int reclimit; 103 104 #ifdef APPLE_HYB 105 /* if we are using the HFS name, we don't want the '/' character */ 106 static void 107 rstrncpy(char *t, char *f, int c) 108 { 109 while (c-- && *f) { 110 switch (*f) { 111 case '/': 112 *t = '_'; 113 break; 114 default: 115 *t = *f; 116 break; 117 } 118 t++; f++; 119 } 120 } 121 #endif /* APPLE HYB */ 122 123 static void add_CE_entry __PR((void)); 124 125 static void add_CE_entry(){ 126 if(recstart) 127 set_733((char*)Rock + recstart - 8, ipnt + 28 - recstart); 128 Rock[ipnt++] ='C'; 129 Rock[ipnt++] ='E'; 130 Rock[ipnt++] = CE_SIZE; 131 Rock[ipnt++] = SU_VERSION; 132 set_733((char*)Rock + ipnt, 0); 133 ipnt += 8; 134 set_733((char*)Rock + ipnt, 0); 135 ipnt += 8; 136 set_733((char*)Rock + ipnt, 0); 137 ipnt += 8; 138 recstart = ipnt; 139 currlen = 0; 140 if(!mainrec) mainrec = ipnt; 141 reclimit = SECTOR_SIZE - 8; /* Limit to one sector */ 142 } 143 144 #ifdef __STDC__ 145 int generate_rock_ridge_attributes (char * whole_name, char * name, 146 struct directory_entry * s_entry, 147 struct stat * statbuf, 148 struct stat * lstatbuf, 149 int deep_opt) 150 #else 151 int generate_rock_ridge_attributes (whole_name, name, 152 s_entry, 153 statbuf, 154 lstatbuf, 155 deep_opt) 156 char * whole_name; char * name; struct directory_entry * s_entry; 157 struct stat * statbuf, *lstatbuf; 158 int deep_opt; 159 #endif 160 { 161 int flagpos, flagval; 162 int need_ce; 163 164 statbuf = statbuf; /* this shuts up unreferenced compiler warnings */ 165 mainrec = recstart = ipnt = 0; 166 reclimit = 0xf8; 167 168 /* no need to fill in the RR stuff if we won't see the file */ 169 if (s_entry->de_flags & INHIBIT_ISO9660_ENTRY) 170 return 0; 171 172 /* Obtain the amount of space that is currently used for the directory 173 record. Assume max for name, since name conflicts may cause us 174 to rename the file later on */ 175 currlen = sizeof(s_entry->isorec); 176 177 #ifdef APPLE_HYB 178 /* if we have regular file, then add Apple extensions */ 179 if (S_ISREG(lstatbuf->st_mode) && apple_ext && s_entry->hfs_ent) { 180 Rock[ipnt++] ='A'; /* AppleSignature */ 181 Rock[ipnt++] ='A'; 182 Rock[ipnt++] = AA_SIZE; /* includes AppleSignature bytes */ 183 Rock[ipnt++] = 0x02; /* SystemUseID */ 184 Rock[ipnt++] = s_entry->hfs_ent->type[0]; 185 Rock[ipnt++] = s_entry->hfs_ent->type[1]; 186 Rock[ipnt++] = s_entry->hfs_ent->type[2]; 187 Rock[ipnt++] = s_entry->hfs_ent->type[3]; 188 Rock[ipnt++] = s_entry->hfs_ent->creator[0]; 189 Rock[ipnt++] = s_entry->hfs_ent->creator[1]; 190 Rock[ipnt++] = s_entry->hfs_ent->creator[2]; 191 Rock[ipnt++] = s_entry->hfs_ent->creator[3]; 192 Rock[ipnt++] = (s_entry->hfs_ent->fdflags >> 8) & 0xff; 193 Rock[ipnt++] = s_entry->hfs_ent->fdflags & 0xff; 194 } 195 #endif /* APPLE_HYB */ 196 197 /* Identify that we are using the SUSP protocol */ 198 if(deep_opt & NEED_SP){ 199 Rock[ipnt++] ='S'; 200 Rock[ipnt++] ='P'; 201 Rock[ipnt++] = 7; 202 Rock[ipnt++] = SU_VERSION; 203 Rock[ipnt++] = 0xbe; 204 Rock[ipnt++] = 0xef; 205 Rock[ipnt++] = 0; 206 }; 207 208 /* First build the posix name field */ 209 Rock[ipnt++] ='R'; 210 Rock[ipnt++] ='R'; 211 Rock[ipnt++] = 5; 212 Rock[ipnt++] = SU_VERSION; 213 flagpos = ipnt; 214 flagval = 0; 215 Rock[ipnt++] = 0; /* We go back and fix this later */ 216 217 if(strcmp(name,".") && strcmp(name,"..")){ 218 char * npnt; 219 int remain, use; 220 221 #ifdef APPLE_HYB 222 /* use the HFS name if it exists */ 223 if (USE_MAC_NAME(mac_name, s_entry)) { 224 remain = strlen(s_entry->hfs_ent->name); 225 npnt = s_entry->hfs_ent->name; 226 } 227 else { 228 #endif 229 230 remain = strlen(name); 231 npnt = name; 232 #ifdef APPLE_HYB 233 } 234 #endif /* APPLE_HYB */ 235 236 while(remain){ 237 use = remain; 238 need_ce = 0; 239 /* Can we fit this SUSP and a CE entry? */ 240 if(use + currlen + CE_SIZE + (ipnt - recstart) > reclimit) { 241 use = reclimit - currlen - CE_SIZE - (ipnt - recstart); 242 need_ce++; 243 } 244 245 /* Only room for 256 per SUSP field */ 246 if(use > 0xf8) use = 0xf8; 247 248 /* First build the posix name field */ 249 Rock[ipnt++] ='N'; 250 Rock[ipnt++] ='M'; 251 Rock[ipnt++] = NM_SIZE + use; 252 Rock[ipnt++] = SU_VERSION; 253 Rock[ipnt++] = (remain != use ? 1 : 0); 254 flagval |= (1<<3); 255 #ifdef APPLE_HYB 256 /* filter out any '/' character in HFS filename */ 257 if (USE_MAC_NAME(mac_name, s_entry)) 258 rstrncpy((char *)&Rock[ipnt], npnt, use); 259 else 260 #endif /* APPLE_HYB */ 261 strncpy((char *)&Rock[ipnt], npnt, use); 262 npnt += use; 263 ipnt += use; 264 remain -= use; 265 if(remain && need_ce) add_CE_entry(); 266 }; 267 }; 268 269 /* 270 * Add the posix modes 271 */ 272 if(MAYBE_ADD_CE_ENTRY(PX_SIZE)) add_CE_entry(); 273 Rock[ipnt++] ='P'; 274 Rock[ipnt++] ='X'; 275 Rock[ipnt++] = PX_SIZE; 276 Rock[ipnt++] = SU_VERSION; 277 flagval |= (1<<0); 278 set_733((char*)Rock + ipnt, lstatbuf->st_mode); 279 ipnt += 8; 280 set_733((char*)Rock + ipnt, lstatbuf->st_nlink); 281 ipnt += 8; 282 set_733((char*)Rock + ipnt, lstatbuf->st_uid); 283 ipnt += 8; 284 set_733((char*)Rock + ipnt, lstatbuf->st_gid); 285 ipnt += 8; 286 287 /* 288 * Check for special devices 289 */ 290 #ifndef NON_UNIXFS 291 if (S_ISCHR(lstatbuf->st_mode) || S_ISBLK(lstatbuf->st_mode)) { 292 if(MAYBE_ADD_CE_ENTRY(PN_SIZE)) add_CE_entry(); 293 Rock[ipnt++] ='P'; 294 Rock[ipnt++] ='N'; 295 Rock[ipnt++] = PN_SIZE; 296 Rock[ipnt++] = SU_VERSION; 297 flagval |= (1<<1); 298 #if defined(MAJOR_IN_SYSMACROS) || defined(MAJOR_IN_MKDEV) 299 set_733((char*)Rock + ipnt, major(lstatbuf->st_rdev )); 300 ipnt += 8; 301 set_733((char*)Rock + ipnt, minor(lstatbuf->st_rdev)); 302 ipnt += 8; 303 #else 304 /* 305 * If we don't have sysmacros.h, then we have to guess as to how 306 * best to pick apart the device number for major/minor. 307 * Note: this may very well be wrong for many systems, so 308 * it is always best to use the major/minor macros if the 309 * system supports it. 310 */ 311 if(sizeof(dev_t) <= 2) { 312 set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 8)); 313 ipnt += 8; 314 set_733((char*)Rock + ipnt, lstatbuf->st_rdev & 0xff); 315 ipnt += 8; 316 } 317 else if(sizeof(dev_t) <= 4) { 318 set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 8) >> 8); 319 ipnt += 8; 320 set_733((char*)Rock + ipnt, lstatbuf->st_rdev & 0xffff); 321 ipnt += 8; 322 } 323 else { 324 set_733((char*)Rock + ipnt, (lstatbuf->st_rdev >> 16) >> 16); 325 ipnt += 8; 326 set_733((char*)Rock + ipnt, lstatbuf->st_rdev); 327 ipnt += 8; 328 } 329 #endif 330 }; 331 #endif 332 /* 333 * Check for and symbolic links. VMS does not have these. 334 */ 335 if (S_ISLNK(lstatbuf->st_mode)){ 336 int lenpos, lenval, j0, j1; 337 int nchar; 338 unsigned char * cpnt, *cpnt1; 339 nchar = readlink(whole_name, (char *)symlink_buff, sizeof(symlink_buff)-1); 340 symlink_buff[nchar < 0 ? 0 : nchar] = 0; 341 nchar = strlen((char *) symlink_buff); 342 set_733(s_entry->isorec.size, 0); 343 cpnt = &symlink_buff[0]; 344 flagval |= (1<<2); 345 346 if (! split_SL_field) 347 { 348 int sl_bytes = 0; 349 for (cpnt1 = cpnt; *cpnt1 != '\0'; cpnt1++) 350 { 351 if (*cpnt1 == '/') 352 { 353 sl_bytes += 4; 354 } 355 else 356 { 357 sl_bytes += 1; 358 } 359 } 360 if (sl_bytes > 250) 361 { 362 /* 363 * the symbolic link won't fit into one SL System Use Field 364 * print an error message and continue with splited one 365 */ 366 fprintf(stderr,"symbolic link ``%s'' to long for one SL System Use Field, splitting", cpnt); 367 } 368 if(MAYBE_ADD_CE_ENTRY(SL_SIZE + sl_bytes)) add_CE_entry(); 369 } 370 371 while(nchar){ 372 if(MAYBE_ADD_CE_ENTRY(SL_SIZE)) add_CE_entry(); 373 Rock[ipnt++] ='S'; 374 Rock[ipnt++] ='L'; 375 lenpos = ipnt; 376 Rock[ipnt++] = SL_SIZE; 377 Rock[ipnt++] = SU_VERSION; 378 Rock[ipnt++] = 0; /* Flags */ 379 lenval = 5; 380 while(*cpnt){ 381 cpnt1 = (unsigned char *) strchr((char *) cpnt, '/'); 382 if(cpnt1) { 383 nchar--; 384 *cpnt1 = 0; 385 }; 386 387 /* We treat certain components in a special way. */ 388 if(cpnt[0] == '.' && cpnt[1] == '.' && cpnt[2] == 0){ 389 if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry(); 390 Rock[ipnt++] = SL_PARENT; 391 Rock[ipnt++] = 0; /* length is zero */ 392 lenval += 2; 393 nchar -= 2; 394 } else if(cpnt[0] == '.' && cpnt[1] == 0){ 395 if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry(); 396 Rock[ipnt++] = SL_CURRENT; 397 Rock[ipnt++] = 0; /* length is zero */ 398 lenval += 2; 399 nchar -= 1; 400 } else if(cpnt[0] == 0){ 401 if(MAYBE_ADD_CE_ENTRY(2)) add_CE_entry(); 402 Rock[ipnt++] = SL_ROOT; 403 Rock[ipnt++] = 0; /* length is zero */ 404 lenval += 2; 405 } else { 406 /* If we do not have enough room for a component, start 407 a new continuations segment now */ 408 if(split_SL_component ? MAYBE_ADD_CE_ENTRY(6) : 409 MAYBE_ADD_CE_ENTRY(6 + strlen ((char *) cpnt))) 410 { 411 add_CE_entry(); 412 if(cpnt1) 413 { 414 *cpnt1 = '/'; 415 nchar++; 416 cpnt1 = NULL; /* A kluge so that we can restart properly */ 417 } 418 break; 419 } 420 j0 = strlen((char *) cpnt); 421 while(j0) { 422 j1 = j0; 423 if(j1 > 0xf8) j1 = 0xf8; 424 need_ce = 0; 425 if(j1 + currlen + CE_SIZE + (ipnt - recstart) > reclimit) { 426 j1 = reclimit - currlen - CE_SIZE - (ipnt - recstart); 427 need_ce++; 428 } 429 Rock[ipnt++] = (j1 != j0 ? SL_CONTINUE : 0); 430 Rock[ipnt++] = j1; 431 strncpy((char *) Rock + ipnt, (char *) cpnt, j1); 432 ipnt += j1; 433 lenval += j1 + 2; 434 cpnt += j1; 435 nchar -= j1; /* Number we processed this time */ 436 j0 -= j1; 437 if(need_ce) { 438 add_CE_entry(); 439 if(cpnt1) { 440 *cpnt1 = '/'; 441 nchar++; 442 cpnt1 = NULL; /* A kluge so that we can restart properly */ 443 } 444 break; 445 } 446 } 447 }; 448 if(cpnt1) { 449 cpnt = cpnt1 + 1; 450 } else 451 break; 452 } 453 Rock[lenpos] = lenval; 454 if(nchar) Rock[lenpos + 2] = SL_CONTINUE; /* We need another SL entry */ 455 } /* while nchar */ 456 } /* Is a symbolic link */ 457 /* 458 * Add in the Rock Ridge TF time field 459 */ 460 if(MAYBE_ADD_CE_ENTRY(TF_SIZE)) add_CE_entry(); 461 Rock[ipnt++] ='T'; 462 Rock[ipnt++] ='F'; 463 Rock[ipnt++] = TF_SIZE; 464 Rock[ipnt++] = SU_VERSION; 465 #ifdef __QNX__ 466 Rock[ipnt++] = 0x0f; 467 #else 468 Rock[ipnt++] = 0x0e; 469 #endif 470 flagval |= (1<<7); 471 #ifdef __QNX__ 472 iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ftime); 473 ipnt += 7; 474 #endif 475 iso9660_date((char *) &Rock[ipnt], lstatbuf->st_mtime); 476 ipnt += 7; 477 iso9660_date((char *) &Rock[ipnt], lstatbuf->st_atime); 478 ipnt += 7; 479 iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ctime); 480 ipnt += 7; 481 482 /* 483 * Add in the Rock Ridge RE time field 484 */ 485 if(deep_opt & NEED_RE){ 486 if(MAYBE_ADD_CE_ENTRY(RE_SIZE)) add_CE_entry(); 487 Rock[ipnt++] ='R'; 488 Rock[ipnt++] ='E'; 489 Rock[ipnt++] = RE_SIZE; 490 Rock[ipnt++] = SU_VERSION; 491 flagval |= (1<<6); 492 }; 493 /* 494 * Add in the Rock Ridge PL record, if required. 495 */ 496 if(deep_opt & NEED_PL){ 497 if(MAYBE_ADD_CE_ENTRY(PL_SIZE)) add_CE_entry(); 498 Rock[ipnt++] ='P'; 499 Rock[ipnt++] ='L'; 500 Rock[ipnt++] = PL_SIZE; 501 Rock[ipnt++] = SU_VERSION; 502 set_733((char*)Rock + ipnt, 0); 503 ipnt += 8; 504 flagval |= (1<<5); 505 }; 506 507 /* 508 * Add in the Rock Ridge CL field, if required. 509 */ 510 if(deep_opt & NEED_CL){ 511 if(MAYBE_ADD_CE_ENTRY(CL_SIZE)) add_CE_entry(); 512 Rock[ipnt++] ='C'; 513 Rock[ipnt++] ='L'; 514 Rock[ipnt++] = CL_SIZE; 515 Rock[ipnt++] = SU_VERSION; 516 set_733((char*)Rock + ipnt, 0); 517 ipnt += 8; 518 flagval |= (1<<4); 519 }; 520 521 #ifndef VMS 522 /* If transparent compression was requested, fill in the correct 523 field for this file */ 524 if(transparent_compression && 525 S_ISREG(lstatbuf->st_mode) && 526 strlen(name) > 3 && 527 strcmp(name + strlen(name) - 3,".gZ") == 0){ 528 FILE * zipfile; 529 char * checkname; 530 unsigned int file_size; 531 unsigned char header[8]; 532 int OK_flag; 533 534 /* First open file and verify that the correct algorithm was used */ 535 file_size = 0; 536 OK_flag = 1; 537 538 zipfile = fopen(whole_name, "rb"); 539 fread(header, 1, sizeof(header), zipfile); 540 541 /* Check some magic numbers from gzip. */ 542 if(header[0] != 0x1f || header[1] != 0x8b || header[2] != 8) OK_flag = 0; 543 /* Make sure file was blocksized. */ 544 if(((header[3] & 0x40) == 0)) OK_flag = 0; 545 /* OK, now go to the end of the file and get some more info */ 546 if(OK_flag){ 547 int status; 548 status = (long)lseek(fileno(zipfile), (off_t)(-8), SEEK_END); 549 if(status == -1) OK_flag = 0; 550 } 551 if(OK_flag){ 552 if(read(fileno(zipfile), (char*)header, sizeof(header)) != sizeof(header)) 553 OK_flag = 0; 554 else { 555 int blocksize; 556 blocksize = (header[3] << 8) | header[2]; 557 file_size = ((unsigned int)header[7] << 24) | 558 ((unsigned int)header[6] << 16) | 559 ((unsigned int)header[5] << 8) | header[4]; 560 #if 0 561 fprintf(stderr,"Blocksize = %d %d\n", blocksize, file_size); 562 #endif 563 if(blocksize != SECTOR_SIZE) OK_flag = 0; 564 } 565 } 566 fclose(zipfile); 567 568 checkname = strdup(whole_name); 569 checkname[strlen(whole_name)-3] = 0; 570 zipfile = fopen(checkname, "rb"); 571 if(zipfile) { 572 OK_flag = 0; 573 fprintf(stderr,"Unable to insert transparent compressed file - name conflict\n"); 574 fclose(zipfile); 575 } 576 577 free(checkname); 578 579 if(OK_flag){ 580 if(MAYBE_ADD_CE_ENTRY(ZZ_SIZE)) add_CE_entry(); 581 Rock[ipnt++] ='Z'; 582 Rock[ipnt++] ='Z'; 583 Rock[ipnt++] = ZZ_SIZE; 584 Rock[ipnt++] = SU_VERSION; 585 Rock[ipnt++] = 'g'; /* Identify compression technique used */ 586 Rock[ipnt++] = 'z'; 587 Rock[ipnt++] = 3; 588 set_733((char*)Rock + ipnt, file_size); /* Real file size */ 589 ipnt += 8; 590 }; 591 } 592 #endif 593 /* 594 * Add in the Rock Ridge CE field, if required. We use this for the 595 * extension record that is stored in the root directory. 596 */ 597 if(deep_opt & NEED_CE) add_CE_entry(); 598 /* 599 * Done filling in all of the fields. Now copy it back to a buffer for the 600 * file in question. 601 */ 602 603 /* Now copy this back to the buffer for the file */ 604 Rock[flagpos] = flagval; 605 606 /* If there was a CE, fill in the size field */ 607 if(recstart) 608 set_733((char*)Rock + recstart - 8, ipnt - recstart); 609 610 s_entry->rr_attributes = (unsigned char *) e_malloc(ipnt); 611 s_entry->total_rr_attr_size = ipnt; 612 s_entry->rr_attr_size = (mainrec ? mainrec : ipnt); 613 memcpy(s_entry->rr_attributes, Rock, ipnt); 614 return ipnt; 615 } 616 617 /* Guaranteed to return a single sector with the relevant info */ 618 619 char * FDECL4(generate_rr_extension_record, char *, id, char *, descriptor, 620 char *, source, int *, size){ 621 int lipnt = 0; 622 char * pnt; 623 int len_id, len_des, len_src; 624 625 len_id = strlen(id); 626 len_des = strlen(descriptor); 627 len_src = strlen(source); 628 Rock[lipnt++] ='E'; 629 Rock[lipnt++] ='R'; 630 Rock[lipnt++] = ER_SIZE + len_id + len_des + len_src; 631 Rock[lipnt++] = 1; 632 Rock[lipnt++] = len_id; 633 Rock[lipnt++] = len_des; 634 Rock[lipnt++] = len_src; 635 Rock[lipnt++] = 1; 636 637 memcpy(Rock + lipnt, id, len_id); 638 lipnt += len_id; 639 640 memcpy(Rock + lipnt, descriptor, len_des); 641 lipnt += len_des; 642 643 memcpy(Rock + lipnt, source, len_src); 644 lipnt += len_src; 645 646 if(lipnt > SECTOR_SIZE) { 647 fprintf(stderr,"Extension record too long\n"); 648 exit(1); 649 }; 650 pnt = (char *) e_malloc(SECTOR_SIZE); 651 memset(pnt, 0, SECTOR_SIZE); 652 memcpy(pnt, Rock, lipnt); 653 *size = lipnt; 654 return pnt; 655 } 656