home *** CD-ROM | disk | FTP | other *** search
- /*
- * File rock.c - generate RRIP records for iso9660 filesystems.
-
- Written by Eric Youngdale (1993).
-
- Copyright 1993 Yggdrasil Computing, Incorporated
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include <stdlib.h>
-
- #ifndef AMIGA
- #ifndef VMS
- #ifndef __QNX__
- #include <sys/sysmacros.h>
- #endif
- #include <unistd.h>
- #endif
- #endif
-
- #include "mkisofs.h"
- #include "iso9660.h"
- #include <string.h>
-
- #ifdef VMS
- #define S_ISLNK(m) (0)
- #else
- #ifndef S_ISLNK
- #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
- #endif
- #endif
-
- #define SU_VERSION 1
-
- #define SL_ROOT 8
- #define SL_PARENT 4
- #define SL_CURRENT 2
- #define SL_CONTINUE 1
-
- /*
- * Buffer to build RR attributes
- */
-
- static unsigned char Rock[16384];
- static unsigned char symlink_buff[256];
-
- #ifdef __STDC__
- int generate_rock_ridge_attributes (char * whole_name, char * name,
- struct directory_entry * s_entry,
- struct stat * statbuf,
- struct stat * lstatbuf,
- int deep_opt)
- #else
- int generate_rock_ridge_attributes (whole_name, name,
- s_entry,
- statbuf,
- lstatbuf,
- deep_opt)
- char * whole_name; char * name; struct directory_entry * s_entry;
- struct stat * statbuf, *lstatbuf;
- int deep_opt;
- #endif
- {
- int ipnt = 0;
- int flagpos, flagval;
-
- statbuf = statbuf; /* this shuts up unreferenced compiler warnings */
-
- /* Identify that we are using the SUSP protocol */
- if(deep_opt & NEED_SP){
- Rock[ipnt++] ='S';
- Rock[ipnt++] ='P';
- Rock[ipnt++] = 7;
- Rock[ipnt++] = SU_VERSION;
- Rock[ipnt++] = 0xbe;
- Rock[ipnt++] = 0xef;
- Rock[ipnt++] = 0;
- };
-
- /* First build the posix name field */
- Rock[ipnt++] ='R';
- Rock[ipnt++] ='R';
- Rock[ipnt++] = 5;
- Rock[ipnt++] = SU_VERSION;
- flagpos = ipnt;
- flagval = 0;
- Rock[ipnt++] = 0; /* We go back and fix this later */
-
- if(strcmp(name,".") && strcmp(name,"..")){
- /* First build the posix name field */
- Rock[ipnt++] ='N';
- Rock[ipnt++] ='M';
- Rock[ipnt++] = 5 + strlen(name);
- Rock[ipnt++] = SU_VERSION;
- Rock[ipnt++] = 0;
- flagval |= (1<<3);
- strcpy((char *)&Rock[ipnt], name);
- ipnt += strlen(name);
- };
-
- /*
- * Add the posix modes
- */
- Rock[ipnt++] ='P';
- Rock[ipnt++] ='X';
- Rock[ipnt++] = 36;
- Rock[ipnt++] = SU_VERSION;
- flagval |= (1<<0);
- set_733((char*)Rock + ipnt, lstatbuf->st_mode);
- ipnt += 8;
- set_733((char*)Rock + ipnt, lstatbuf->st_nlink);
- ipnt += 8;
- set_733((char*)Rock + ipnt, lstatbuf->st_uid);
- ipnt += 8;
- set_733((char*)Rock + ipnt, lstatbuf->st_gid);
- ipnt += 8;
-
- #ifndef AMIGA
-
- /*
- * Check for special devices
- */
- if (S_ISCHR(lstatbuf->st_mode) || S_ISBLK(lstatbuf->st_mode)) {
- Rock[ipnt++] ='P';
- Rock[ipnt++] ='N';
- Rock[ipnt++] = 20;
- Rock[ipnt++] = SU_VERSION;
- flagval |= (1<<1);
- set_733((char*)Rock + ipnt, major(lstatbuf->st_rdev));
- ipnt += 8;
- set_733((char*)Rock + ipnt, minor(lstatbuf->st_rdev));
- ipnt += 8;
- };
-
- /*
- * Check for and symbolic links. VMS does not have these.
- */
- if (S_ISLNK(lstatbuf->st_mode)){
- int lenpos, lenval, j0;
- int cflag, nchar;
- unsigned char * cpnt, *cpnt1;
- nchar = readlink(whole_name, symlink_buff, sizeof(symlink_buff));
- symlink_buff[nchar] = 0;
- set_733(s_entry->isorec.size, 0);
- Rock[ipnt++] ='S';
- Rock[ipnt++] ='L';
- lenpos = ipnt;
- Rock[ipnt++] = 20;
- Rock[ipnt++] = SU_VERSION;
- Rock[ipnt++] = 0;
- flagval |= (1<<2);
- lenval = 5;
- cpnt = &symlink_buff[0];
- while(*cpnt){
- cpnt1 = (unsigned char *) strchr((char *) cpnt, '/');
- cflag = 0;
- if(cpnt1) {
- *cpnt1 = 0;
- };
-
- /* We treat certain components in a special way. */
- if(cpnt[0] == '.' && cpnt[1] == '.' && cpnt[2] == 0){
- Rock[ipnt++] = SL_PARENT | cflag;
- Rock[ipnt++] = 0; /* length is zero */
- lenval += 2;
- } else if(cpnt[0] == '.' && cpnt[1] == 0){
- Rock[ipnt++] = SL_CURRENT | cflag;
- Rock[ipnt++] = 0; /* length is zero */
- lenval += 2;
- } else if(cpnt[0] == 0){
- Rock[ipnt++] = SL_ROOT | cflag;
- Rock[ipnt++] = 0; /* length is zero */
- lenval += 2;
- } else {
- Rock[ipnt++] = cflag;
- j0 = strlen((char *) cpnt);
- Rock[ipnt++] = j0;
- strcpy((char *) Rock + ipnt, (char *) cpnt);
- ipnt += j0;
- lenval += j0 + 2;
- };
- if(cpnt1)
- cpnt = cpnt1 + 1;
- else
- break;
- };
- Rock[lenpos] = lenval;
- };
-
- #endif
-
- /*
- * Add in the Rock Ridge TF time field
- */
- Rock[ipnt++] ='T';
- Rock[ipnt++] ='F';
- #ifdef __QNX__
- Rock[ipnt++] = 5 + 4 * 7;
- Rock[ipnt++] = SU_VERSION;
- Rock[ipnt++] = 0x0f;
- #else
- Rock[ipnt++] = 5 + 3 * 7;
- Rock[ipnt++] = SU_VERSION;
- Rock[ipnt++] = 0x0e;
- #endif
- flagval |= (1<<7);
- #ifdef __QNX__
- iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ftime);
- ipnt += 7;
- #endif
- iso9660_date((char *) &Rock[ipnt], lstatbuf->st_mtime);
- ipnt += 7;
- iso9660_date((char *) &Rock[ipnt], lstatbuf->st_atime);
- ipnt += 7;
- iso9660_date((char *) &Rock[ipnt], lstatbuf->st_ctime);
- ipnt += 7;
-
- /*
- * Add in the Rock Ridge RE time field
- */
- if(deep_opt & NEED_RE){
- Rock[ipnt++] ='R';
- Rock[ipnt++] ='E';
- Rock[ipnt++] = 4;
- Rock[ipnt++] = SU_VERSION;
- flagval |= (1<<6);
- };
- /*
- * Add in the Rock Ridge PL record, if required.
- */
- if(deep_opt & NEED_PL){
- Rock[ipnt++] ='P';
- Rock[ipnt++] ='L';
- Rock[ipnt++] = 12;
- Rock[ipnt++] = SU_VERSION;
- set_733((char*)Rock + ipnt, 0);
- ipnt += 8;
- flagval |= (1<<5);
- };
-
- /*
- * Add in the Rock Ridge CL field, if required.
- */
- if(deep_opt & NEED_CL){
- Rock[ipnt++] ='C';
- Rock[ipnt++] ='L';
- Rock[ipnt++] = 12;
- Rock[ipnt++] = SU_VERSION;
- set_733((char*)Rock + ipnt, 0);
- ipnt += 8;
- flagval |= (1<<4);
- };
-
- /*
- * Add in the Rock Ridge CE field, if required. We use this for the
- * extension record that is stored in the root directory.
- */
- if(deep_opt & NEED_CE){
- Rock[ipnt++] ='C';
- Rock[ipnt++] ='E';
- Rock[ipnt++] = 28;
- Rock[ipnt++] = SU_VERSION;
- set_733((char*)Rock + ipnt, 0);
- ipnt += 8;
- set_733((char*)Rock + ipnt, 0);
- ipnt += 8;
- set_733((char*)Rock + ipnt, 0);
- ipnt += 8;
- };
-
- /*
- * Done filling in all of the fields. Now copy it back to a buffer for the
- * file in question.
- */
-
- /* Now copy this back to the buffer for the file */
- Rock[flagpos] = flagval;
-
- s_entry->rr_attributes = (char *) malloc(ipnt);
- s_entry->rr_attr_size = ipnt;
- memcpy(s_entry->rr_attributes, Rock, ipnt);
- return ipnt;
- }
-
- /* Guaranteed to return a single sector with the relevant info */
-
- char * FDECL4(generate_rr_extension_record, char *, id, char *, descriptor,
- char *, source, int *, size){
- int ipnt = 0;
- char * pnt;
- int len_id, len_des, len_src;
-
- len_id = strlen(id);
- len_des = strlen(descriptor);
- len_src = strlen(source);
- Rock[ipnt++] ='E';
- Rock[ipnt++] ='R';
- Rock[ipnt++] = 8 + len_id + len_des + len_src;
- Rock[ipnt++] = 1;
- Rock[ipnt++] = len_id;
- Rock[ipnt++] = len_des;
- Rock[ipnt++] = len_src;
- Rock[ipnt++] = 1;
-
- memcpy(Rock + ipnt, id, len_id);
- ipnt += len_id;
-
- memcpy(Rock + ipnt, descriptor, len_des);
- ipnt += len_des;
-
- memcpy(Rock + ipnt, source, len_src);
- ipnt += len_src;
-
- if(ipnt > SECTOR_SIZE) {
- fprintf(stderr,"Extension record too long\n");
- exit(1);
- };
- pnt = (char *) malloc(SECTOR_SIZE);
- memset(pnt, 0, SECTOR_SIZE);
- memcpy(pnt, Rock, ipnt);
- *size = ipnt;
- return pnt;
- }
-