home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 9
/
FreshFishVol9-CD2.bin
/
bbs
/
disk
/
mkisofs-1.00.7.lha
/
mkisofs
/
rock.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-05-29
|
8KB
|
336 lines
/*
* 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;
}