9f107b5f80
- fetch: Go CLI tool for searching, downloading, and extracting AKAI sampler ISOs from archive.org - scripts/extract_wavs.sh: Shell script driving akaiutil to convert samples to WAV - Dockerfile: Multi-stage build packaging akaiutil + fetch - third_party/akaiutil: Vendored akaiutil v4.6.7 source (GPLv2) - docs/akaiutil.md: Full akaiutil reference
1236 lines
34 KiB
C
Executable File
1236 lines
34 KiB
C
Executable File
/*
|
|
* Copyright (C) 2008,2010,2012,2018,2019,2020,2021 Klaus Michael Indlekofer. All rights reserved.
|
|
*
|
|
* m.indlekofer@gmx.de
|
|
*
|
|
* 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
|
|
* of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
|
|
|
|
#include "commoninclude.h"
|
|
#include "akaiutil_io.h"
|
|
#include "akaiutil.h"
|
|
#include "akaiutil_file.h"
|
|
#include "akaiutil_take.h"
|
|
#include "akaiutil_tar.h"
|
|
|
|
|
|
|
|
u_int
|
|
tar_checksum(u_char *hp)
|
|
{
|
|
u_int sum;
|
|
u_int i;
|
|
int zeroflag;
|
|
|
|
if (hp==NULL){
|
|
return 0;
|
|
}
|
|
|
|
sum=0;
|
|
zeroflag=1; /* still all zeroes */
|
|
for (i=0;i<sizeof(struct tar_head_s);i++){
|
|
if (hp[i]!=0){
|
|
zeroflag=0;
|
|
}
|
|
if ((i>=148)&&(i<156)){ /* treat chksum field */
|
|
sum+=(u_int)' '; /* space */
|
|
}else{
|
|
sum+=(u_int)hp[i];
|
|
}
|
|
}
|
|
/* Note: sum is always >0 !!! */
|
|
|
|
if (zeroflag){
|
|
sum=0; /* unique value, see comment above */
|
|
}
|
|
return sum;
|
|
}
|
|
|
|
int
|
|
tar_export(int fd,struct disk_s *dp,struct part_s *pp,struct vol_s *vp,struct file_s *fp,u_int ti,u_int flags,int verbose,u_char *filtertagp)
|
|
{
|
|
struct tar_head_s tarhd;
|
|
u_int chksum;
|
|
u_int size;
|
|
u_int n;
|
|
u_char buf[TAR_BLOCKSIZE];
|
|
int wavret;
|
|
char *wavname;
|
|
int wavconvflag;
|
|
|
|
/* DD take */
|
|
u_int ddcstarts,ddcstarte;
|
|
u_int ddcsizes,ddcsizee;
|
|
struct akai_ddtake_s ddt;
|
|
|
|
if (fd<0){
|
|
return -1;
|
|
}
|
|
if ((flags&(TAR_EXPORT_DISK|TAR_EXPORT_PART|TAR_EXPORT_VOL|TAR_EXPORT_ANYFILE))==0){
|
|
return -1;
|
|
}
|
|
|
|
size=0;
|
|
|
|
ddcstarts=0;
|
|
ddcstarte=0;
|
|
ddcsizes=0;
|
|
ddcsizee=0;
|
|
|
|
wavconvflag=0;
|
|
|
|
/* create tar header */
|
|
bzero(&tarhd,sizeof(struct tar_head_s));
|
|
|
|
/* name */
|
|
/* XXX should always fit */
|
|
if (flags&TAR_EXPORT_DISK){
|
|
/* disk */
|
|
if (dp==NULL){
|
|
return -1;
|
|
}
|
|
sprintf(tarhd.name,"disk%u/",dp->index);
|
|
}
|
|
if (flags&TAR_EXPORT_PART){
|
|
/* partition */
|
|
if (pp==NULL){
|
|
return -1;
|
|
}
|
|
if (pp->type==PART_TYPE_DD){
|
|
/* harddisk DD partition */
|
|
if (pp->letter==0){
|
|
sprintf(tarhd.name+strlen(tarhd.name),"DD/");
|
|
}else{
|
|
sprintf(tarhd.name+strlen(tarhd.name),"DD%u/",(u_int)pp->letter);
|
|
}
|
|
}else{
|
|
/* sampler partition */
|
|
sprintf(tarhd.name+strlen(tarhd.name),"%c/",pp->letter);
|
|
}
|
|
}
|
|
if (flags&TAR_EXPORT_VOL){
|
|
/* sampler volume */
|
|
if ((vp==NULL)||(vp->type==AKAI_VOL_TYPE_INACT)){
|
|
return -1;
|
|
}
|
|
sprintf(tarhd.name+strlen(tarhd.name),"%s/",vp->name);
|
|
if ((flags&TAR_EXPORT_ANYFILE)==0){ /* not a file? */
|
|
/* XXX use devmajor field for type */
|
|
sprintf(tarhd.devmajor,"%07o",vp->type);
|
|
/* XXX use devminor field for load number */
|
|
sprintf(tarhd.devminor,"%07o",vp->lnum);
|
|
#ifndef TAR_NOVOLPARAMTARHD
|
|
if (vp->param!=NULL){
|
|
/* XXX use linkname for volume parameters */
|
|
tarhd.linkname[0]='\0'; /* XXX magic, also empty linkname string */
|
|
tarhd.linkname[1]='P'; /* XXX magic */
|
|
bcopy(vp->param,
|
|
&tarhd.linkname[0]+2, /* XXX +2: linkname starts with magic */
|
|
sizeof(struct akai_volparam_s)); /* XXX should fit */
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
if (flags&TAR_EXPORT_DDFILE){
|
|
/* DD take */
|
|
if (flags&TAR_EXPORT_WAV){
|
|
wavret=akai_take2wav(pp,ti,fd,&size,&wavname,TAKE2WAV_CHECK);
|
|
if (wavret<0){ /* error? */
|
|
#if 1
|
|
return 0; /* skip this file w/o error */
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
strcpy(tarhd.name+strlen(tarhd.name),wavname);
|
|
wavconvflag=1;
|
|
}
|
|
if (!wavconvflag){
|
|
char fnamebuf[AKAI_NAME_LEN+4+1]; /* name (ASCII), +4 for ".<type>", +1 for '\0' */
|
|
|
|
/* index */
|
|
if (ti>=AKAI_DDTAKE_MAXNUM){
|
|
return 0; /* skip this file w/o error */
|
|
}
|
|
if (pp->head.dd.take[ti].stat==AKAI_DDTAKESTAT_FREE){ /* free? */
|
|
return 0; /* skip this file w/o error */
|
|
}
|
|
|
|
/* clusters */
|
|
ddcstarts=(pp->head.dd.take[ti].cstarts[1]<<8)
|
|
+pp->head.dd.take[ti].cstarts[0];
|
|
ddcstarte=(pp->head.dd.take[ti].cstarte[1]<<8)
|
|
+pp->head.dd.take[ti].cstarte[0];
|
|
|
|
/* determine csizes (sample clusters) and csizee (envelope clusters) */
|
|
if (ddcstarts!=0){ /* sample not empty? */
|
|
ddcsizes=akai_count_ddfatchain(pp,ddcstarts);
|
|
}else{
|
|
ddcsizes=0;
|
|
}
|
|
if (ddcstarte!=0){ /* envelope not empty? */
|
|
ddcsizee=akai_count_ddfatchain(pp,ddcstarte);
|
|
}else{
|
|
ddcsizee=0;
|
|
}
|
|
|
|
/* name */
|
|
akai2ascii_name(pp->head.dd.take[ti].name,fnamebuf,0); /* 0: not S900 */
|
|
strcpy(fnamebuf+strlen(fnamebuf),AKAI_DDTAKE_FNAMEEND);
|
|
strcpy(tarhd.name+strlen(tarhd.name),fnamebuf);
|
|
|
|
/* get DD take header (DD directory entry) */
|
|
bcopy(&pp->head.dd.take[ti],&ddt,sizeof(struct akai_ddtake_s));
|
|
/* XXX use cstarts/cstarte fields in DD take header for csizes/csizee */
|
|
ddt.cstarts[1]=0xff&(ddcsizes>>8);
|
|
ddt.cstarts[0]=0xff&ddcsizes;
|
|
ddt.cstarte[1]=0xff&(ddcsizee>>8);
|
|
ddt.cstarte[0]=0xff&ddcsizee;
|
|
/* size in bytes */
|
|
size=sizeof(struct akai_ddtake_s)+(ddcsizes+ddcsizee)*AKAI_DDPART_CBLKS*AKAI_HD_BLOCKSIZE;
|
|
}
|
|
}
|
|
if (flags&TAR_EXPORT_FILE){
|
|
/* sampler file */
|
|
if ((fp==NULL)||(fp->type==AKAI_FTYPE_FREE)){
|
|
return -1;
|
|
}
|
|
/* test if tag-filter matches */
|
|
if (akai_match_filetags(filtertagp,fp->tag)<0){ /* no match? */
|
|
return 0; /* skip this file w/o error */
|
|
}
|
|
if (flags&TAR_EXPORT_WAV){
|
|
wavret=akai_sample2wav(fp,fd,&size,&wavname,SAMPLE2WAV_CHECK);
|
|
if (wavret<0){ /* error? */
|
|
#if 1
|
|
return 0; /* skip this file w/o error */
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
if (wavret==0){
|
|
/* file is a valid sample file */
|
|
strcpy(tarhd.name+strlen(tarhd.name),wavname);
|
|
wavconvflag=1;
|
|
} /* else: file is not a sample file, export without WAV conversion */
|
|
}
|
|
if (!wavconvflag){
|
|
strcpy(tarhd.name+strlen(tarhd.name),fp->name);
|
|
size=fp->size;
|
|
}
|
|
/* XXX use devmajor field for osver */
|
|
if (wavconvflag&&(fp->type==AKAI_SAMPLE900_FTYPE)){ /* WAV conversion of S900 sample file? */
|
|
/* WAV is non-compressed, must use osver for S900 non-compressed sample format */
|
|
sprintf(tarhd.devmajor,"%07o",AKAI_OSVER_S900VOL); /* XXX */
|
|
}else{
|
|
sprintf(tarhd.devmajor,"%07o",fp->osver); /* XXX */
|
|
}
|
|
if ((fp->volp!=NULL)
|
|
&&((fp->volp->type==AKAI_VOL_TYPE_S3000)||(fp->volp->type==AKAI_VOL_TYPE_CD3000))){
|
|
/* XXX use linkname for file tags */
|
|
tarhd.linkname[0]='\0'; /* XXX magic, also empty linkname string */
|
|
tarhd.linkname[1]='T'; /* XXX magic */
|
|
bcopy(fp->tag,
|
|
&tarhd.linkname[0]+2, /* XXX +2: linkname starts with magic */
|
|
AKAI_FILE_TAGNUM); /* XXX should fit */
|
|
}
|
|
}
|
|
#ifndef TAR_NOTAGSFILE
|
|
#ifndef TAR_TAGSFILENAME
|
|
#define TAR_TAGSFILENAME "TAGS.DAT"
|
|
#endif
|
|
if (flags&TAR_EXPORT_TAGSFILE){
|
|
/* tags-file */
|
|
if ((pp==NULL)||(pp->type!=PART_TYPE_HD) /* not in S1000/S3000 harddisk partition on partition level? */
|
|
||(strncmp(AKAI_PARTHEAD_TAGSMAGIC,(char *)pp->head.hd.tagsmagic,4)!=0)){
|
|
#if 1
|
|
return 0; /* skip this file w/o error */
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
strcpy(tarhd.name+strlen(tarhd.name),TAR_TAGSFILENAME);
|
|
size=4+AKAI_PARTHEAD_TAGNUM*AKAI_NAME_LEN; /* tags magic and tag names */;
|
|
}
|
|
#endif
|
|
#ifndef TAR_NOVOLPARAMFILE
|
|
#ifndef TAR_VOLPARAMFILENAME
|
|
#define TAR_VOLPARAMFILENAME "VOLPARAM.DAT"
|
|
#endif
|
|
if (flags&TAR_EXPORT_VOLPARAMFILE){
|
|
/* volparam-file */
|
|
if ((vp==NULL)||(vp->type==AKAI_VOL_TYPE_INACT)||(vp->param==NULL)){
|
|
#if 1
|
|
return 0; /* skip this file w/o error */
|
|
#else
|
|
return -1;
|
|
#endif
|
|
}
|
|
strcpy(tarhd.name+strlen(tarhd.name),TAR_VOLPARAMFILENAME);
|
|
size=sizeof(struct akai_volparam_s);
|
|
}
|
|
#endif
|
|
|
|
if (verbose){
|
|
PRINTF_OUT("%s\n",tarhd.name);
|
|
FLUSH_ALL;
|
|
}
|
|
|
|
/* mode, uid, gid */
|
|
if (flags&TAR_EXPORT_ANYFILE){ /* file? */
|
|
sprintf(tarhd.mode,"%07o",0600); /* XXX -rw------- */
|
|
}else{
|
|
/* directory */
|
|
sprintf(tarhd.mode,"%07o",0700); /* XXX -rwx------ */
|
|
}
|
|
sprintf(tarhd.uid,"%07o",0); /* XXX */
|
|
sprintf(tarhd.gid,"%07o",0); /* XXX */
|
|
|
|
/* size */
|
|
sprintf(tarhd.size,"%011o",size);
|
|
|
|
/* mtime */
|
|
sprintf(tarhd.mtime,"%011o",(u_int)time(NULL)); /* XXX */
|
|
|
|
/* space */
|
|
tarhd.space=' ';
|
|
|
|
/* type */
|
|
if (flags&TAR_EXPORT_ANYFILE){ /* file? */
|
|
tarhd.type=TAR_TYPE_REG;
|
|
}else{
|
|
/* directory */
|
|
tarhd.type=TAR_TYPE_DIR;
|
|
}
|
|
|
|
/* magic */
|
|
bcopy(TAR_USTAR,tarhd.ustar,8);
|
|
|
|
/* user name */
|
|
#ifndef TAR_UNAME
|
|
#define TAR_UNAME "AKAI"
|
|
#endif
|
|
strcpy(tarhd.uname,TAR_UNAME);
|
|
/* group name */
|
|
#ifndef TAR_GNAME
|
|
#define TAR_GNAME "AKAI"
|
|
#endif
|
|
strcpy(tarhd.gname,TAR_GNAME);
|
|
|
|
/* checksum */
|
|
chksum=tar_checksum((u_char *)&tarhd);
|
|
sprintf(tarhd.chksum,"%06o",chksum);
|
|
|
|
/* write tar header */
|
|
if (WRITE(fd,(void *)&tarhd,sizeof(struct tar_head_s))!=sizeof(struct tar_head_s)){
|
|
PRINTF_ERR("cannot write tar header\n");
|
|
return -1;
|
|
}
|
|
|
|
if ((flags&TAR_EXPORT_ANYFILE)==0){ /* not a file? */
|
|
return 0; /* done */
|
|
}
|
|
|
|
if (flags&TAR_EXPORT_DDFILE){
|
|
/* export DD take */
|
|
if (wavconvflag){
|
|
if (akai_take2wav(pp,ti,fd,NULL,NULL,SAMPLE2WAV_EXPORT)<0){
|
|
return -1;
|
|
}
|
|
}else{
|
|
if (akai_export_take(fd,pp,&ddt,ddcsizes,ddcsizee,ddcstarts,ddcstarte)<0){
|
|
PRINTF_ERR("cannot export take\n");
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (flags&TAR_EXPORT_FILE){
|
|
/* export sampler file */
|
|
if (wavconvflag){
|
|
if (akai_sample2wav(fp,fd,NULL,NULL,SAMPLE2WAV_EXPORT)<0){
|
|
return -1;
|
|
}
|
|
}else{
|
|
if (akai_read_file(fd,NULL,fp,0,fp->size)<0){
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifndef TAR_NOTAGSFILE
|
|
if (flags&TAR_EXPORT_TAGSFILE){
|
|
/* export tags-file */
|
|
if (WRITE(fd,(void *)pp->head.hd.tagsmagic,size)!=(int)size){
|
|
PRINTF_ERR("cannot export tags-file\n");
|
|
return -1;
|
|
}
|
|
}
|
|
#endif
|
|
#ifndef TAR_NOVOLPARAMFILE
|
|
if (flags&TAR_EXPORT_VOLPARAMFILE){
|
|
/* export volparam-file */
|
|
if (WRITE(fd,(void *)vp->param,size)!=(int)size){
|
|
PRINTF_ERR("cannot export volparam-file\n");
|
|
return -1;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* fill rest of TAR_BLOCKSIZE bytes */
|
|
n=size%TAR_BLOCKSIZE;
|
|
n=(TAR_BLOCKSIZE-n)%TAR_BLOCKSIZE;
|
|
if (n>0){
|
|
bzero(buf,n);
|
|
/* write */
|
|
if (WRITE(fd,(void *)buf,n)!=(int)n){
|
|
PRINTF_ERR("cannot write rest of block\n");
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
tar_export_vol(int fd,struct vol_s *vp,u_int flags,int verbose,u_char *filtertagp)
|
|
{
|
|
u_int fi;
|
|
struct file_s tmpfile; /* current file */
|
|
|
|
if ((fd<0)||(vp==NULL)||(vp->type==AKAI_VOL_TYPE_INACT)||(vp->partp==NULL)||(!vp->partp->valid)){
|
|
return -1;
|
|
}
|
|
|
|
#ifndef TAR_NOVOLPARAMFILE
|
|
if (vp->param!=NULL){
|
|
/* export volparam-file */
|
|
if (tar_export(fd,vp->partp->diskp,vp->partp,vp,NULL,0,flags|TAR_EXPORT_VOLPARAMFILE,verbose,NULL)){
|
|
return -1;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* files in volume directory */
|
|
for (fi=0;fi<vp->fimax;fi++){
|
|
/* get file */
|
|
if (akai_get_file(vp,&tmpfile,fi)<0){
|
|
continue; /* XXX ignore error, next file */
|
|
}
|
|
#if 1
|
|
if (akai_check_fatblk(tmpfile.bstart,vp->partp->bsize,vp->partp->bsyssize)<0){ /* invalid? */
|
|
if (verbose){
|
|
PRINTF_OUT("file %u has invalid start block, skipping file\n",tmpfile.index+1);
|
|
FLUSH_ALL;
|
|
}
|
|
continue; /* XXX ignore error, next file */
|
|
}
|
|
#endif
|
|
|
|
/* export [part/volume/]file */
|
|
if (tar_export(fd,vp->partp->diskp,vp->partp,vp,&tmpfile,0,flags|TAR_EXPORT_FILE,verbose,filtertagp)){
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
tar_export_part(int fd,struct part_s *pp,u_int flags,int verbose,u_char *filtertagp)
|
|
{
|
|
u_int vi;
|
|
struct vol_s tmpvol; /* current volume */
|
|
|
|
if ((fd<0)||(pp==NULL)||(!pp->valid)){
|
|
return -1;
|
|
}
|
|
|
|
if (pp->type==PART_TYPE_DD){
|
|
/* harddisk DD partition */
|
|
/* export all DD takes */
|
|
u_int ti;
|
|
|
|
for (ti=0;ti<AKAI_DDTAKE_MAXNUM;ti++){
|
|
if (pp->head.dd.take[ti].stat==AKAI_DDTAKESTAT_FREE){ /* free? */
|
|
continue; /* next */
|
|
}
|
|
if (tar_export(fd,pp->diskp,pp,NULL,NULL,ti,flags|TAR_EXPORT_DDFILE,verbose,filtertagp)){
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* now, sampler partition */
|
|
|
|
#ifndef TAR_NOTAGSFILE
|
|
if (pp->type==PART_TYPE_HD){ /* in S1000/S3000 harddisk partition? */
|
|
/* export tags-file */
|
|
/* Note: tar_export() will check for valid tags magic */
|
|
if (tar_export(fd,pp->diskp,pp,NULL,NULL,0,flags|TAR_EXPORT_TAGSFILE,verbose,NULL)){
|
|
return -1;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* volumes in root directory of partition */
|
|
for (vi=0;vi<pp->volnummax;vi++){
|
|
/* get volume */
|
|
if (akai_get_vol(pp,&tmpvol,vi)<0){
|
|
continue; /* XXX ignore error, next volume */
|
|
}
|
|
if ((tmpvol.type!=AKAI_VOL_TYPE_S900)
|
|
&&(tmpvol.type!=AKAI_VOL_TYPE_S1000)
|
|
&&(tmpvol.type!=AKAI_VOL_TYPE_S3000)
|
|
&&(tmpvol.type!=AKAI_VOL_TYPE_CD3000)){
|
|
continue; /* next volume */
|
|
}
|
|
/* create vol/ */
|
|
if (tar_export(fd,pp->diskp,pp,&tmpvol,NULL,0,flags|TAR_EXPORT_VOL,verbose,NULL)){
|
|
return -1;
|
|
}
|
|
/* export volume */
|
|
if (tar_export_vol(fd,&tmpvol,flags|TAR_EXPORT_VOL,verbose,filtertagp)<0){
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
tar_export_disk(int fd,struct disk_s *dp,u_int flags,int verbose,u_char *filtertagp)
|
|
{
|
|
u_int pi;
|
|
|
|
if ((fd<0)||(dp==NULL)){
|
|
return -1;
|
|
}
|
|
|
|
/* partitions on disk */
|
|
for (pi=0;pi<part_num;pi++){
|
|
if (part[pi].diskp!=dp){ /* partition not on disk? */
|
|
continue; /* next partition */
|
|
}
|
|
/* create part/ */
|
|
if (tar_export(fd,part[pi].diskp,&part[pi],NULL,NULL,0,flags|TAR_EXPORT_PART,verbose,NULL)){
|
|
return -1;
|
|
}
|
|
/* export partition (sampler or DD) */
|
|
if (tar_export_part(fd,&part[pi],flags|TAR_EXPORT_PART,verbose,filtertagp)<0){
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
tar_export_alldisks(int fd,u_int flags,int verbose,u_char *filtertagp)
|
|
{
|
|
u_int i;
|
|
|
|
if (fd<0){
|
|
return -1;
|
|
}
|
|
|
|
/* all disks */
|
|
for (i=0;i<disk_num;i++){
|
|
/* create disk/ */
|
|
if (tar_export(fd,&disk[i],NULL,NULL,NULL,0,flags|TAR_EXPORT_DISK,verbose,NULL)){
|
|
return -1;
|
|
}
|
|
/* export disk */
|
|
if (tar_export_disk(fd,&disk[i],flags|TAR_EXPORT_DISK,verbose,filtertagp)<0){
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
tar_export_curdir(int fd,int verbose,u_int flags)
|
|
{
|
|
|
|
if (fd<0){
|
|
return -1;
|
|
}
|
|
|
|
if (curdiskp==NULL){ /* no disk? */
|
|
/* now, on system level */
|
|
return tar_export_alldisks(fd,flags,verbose,curfiltertag);
|
|
}
|
|
if (curpartp==NULL){ /* no partition? */
|
|
/* now, on disk */
|
|
return tar_export_disk(fd,curdiskp,flags,verbose,curfiltertag);
|
|
}
|
|
if (curvolp==NULL){ /* no sampler volume? */
|
|
/* now, in partition (sampler or DD) */
|
|
return tar_export_part(fd,curpartp,flags,verbose,curfiltertag);
|
|
}
|
|
/* now, in sampler volume */
|
|
return tar_export_vol(fd,curvolp,flags,verbose,curfiltertag);
|
|
}
|
|
|
|
int
|
|
tar_export_tailzero(int fd)
|
|
{
|
|
u_char buf[TAR_TAILZERO_BLOCKS*TAR_BLOCKSIZE];
|
|
|
|
/* zero blocks */
|
|
bzero(buf,TAR_TAILZERO_BLOCKS*TAR_BLOCKSIZE);
|
|
|
|
/* write blocks */
|
|
if (WRITE(fd,buf,TAR_TAILZERO_BLOCKS*TAR_BLOCKSIZE)!=TAR_TAILZERO_BLOCKS*TAR_BLOCKSIZE){
|
|
PRINTF_ERR("cannot write zero blocks\n");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
tar_import_curdir(int fd,u_int vtype0,int verbose,u_int flags)
|
|
{
|
|
struct tar_head_s tarhd;
|
|
u_int byteend,skip;
|
|
u_int chksum,chksum0;
|
|
u_int nlen;
|
|
u_int l;
|
|
int i;
|
|
int ret;
|
|
struct vol_s tmpvol;
|
|
struct file_s tmpfile;
|
|
u_int vtype,lnum;
|
|
u_int ftype;
|
|
u_int osver;
|
|
u_char *tagp;
|
|
struct akai_volparam_s *parp;
|
|
u_int wavbcount;
|
|
int wavret;
|
|
u_int ti;
|
|
u_int csizes,csizee;
|
|
u_int tsize;
|
|
struct akai_ddtake_s t;
|
|
|
|
save_curdir(1); /* 1: could be modifications */
|
|
|
|
/* interpret tar file */
|
|
skip=0;
|
|
ret=-1; /* no success so far */
|
|
for (;;){
|
|
if (verbose){
|
|
FLUSH_ALL;
|
|
}
|
|
restore_curdir();
|
|
|
|
/* skip if necessary */
|
|
if (skip>0){
|
|
/* skip file */
|
|
if (LSEEK64(fd,(OFF64_T)skip,SEEK_CUR)<0){
|
|
PERROR("lseek");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
}
|
|
skip=0;
|
|
|
|
/* read header */
|
|
/* XXX size must not exceed SSIZE_MAX! */
|
|
ret=(int)READ(fd,(void *)&tarhd,sizeof(struct tar_head_s));
|
|
if (ret==0){
|
|
/* end of file */
|
|
ret=0; /* success */
|
|
goto tar_import_done;
|
|
}else if (ret!=sizeof(struct tar_head_s)){
|
|
PRINTF_ERR("cannot read tar header\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
|
|
/* check header */
|
|
chksum0=tar_checksum((u_char *)&tarhd);
|
|
if (chksum0==0){ /* all zero block? */
|
|
/* XXX ignore */
|
|
continue; /* next */
|
|
}
|
|
/* checksum */
|
|
if ((sscanf(tarhd.chksum,"%o",&chksum)!=1)||(chksum!=chksum0)){
|
|
PRINTF_OUT("checksum error in next header\n");
|
|
FLUSH_ALL;
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
|
|
/* get size */
|
|
byteend=0; /* default */
|
|
sscanf(tarhd.size,"%o",&byteend);
|
|
/* Note: if sscanf finds nothing, vtype remains! */
|
|
/* skip rest of full TAR_BLOCKSIZE */
|
|
skip=byteend%TAR_BLOCKSIZE;
|
|
skip=(TAR_BLOCKSIZE-skip)%TAR_BLOCKSIZE;
|
|
|
|
/* check type */
|
|
if ((tarhd.type!=TAR_TYPE_DIR)
|
|
&&(tarhd.type!=TAR_TYPE_REG)
|
|
&&(tarhd.type!=TAR_TYPE_REG0)){
|
|
skip+=byteend; /* skip file */
|
|
continue; /* next */
|
|
}
|
|
/* now, directory or regular file */
|
|
|
|
/* get name */
|
|
if (verbose){
|
|
PRINTF_OUT("%s\n",tarhd.name);
|
|
FLUSH_ALL;
|
|
}
|
|
l=(u_int)strlen(tarhd.name);
|
|
/* correct name if directory */
|
|
if ((tarhd.type==TAR_TYPE_DIR)&&(l>0)&&(tarhd.name[l-1]=='/')){
|
|
tarhd.name[l-1]='\0'; /* terminate */
|
|
l--;
|
|
}
|
|
if (l==0){
|
|
if (verbose){
|
|
PRINTF_OUT("empty name, skipping file\n");
|
|
FLUSH_ALL;
|
|
}
|
|
skip+=byteend; /* skip file */
|
|
continue; /* next */
|
|
}
|
|
|
|
/* XXX ignore other tarhd elements */
|
|
|
|
/* change to upper level directory */
|
|
/* Note: will be undone upon exit or next for-loop iteration */
|
|
save_curdir(1); /* 1: could be modifications */
|
|
if (change_curdir(tarhd.name,0,dirnamebuf,0)<0){
|
|
PRINTF_ERR("directory not found\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
|
|
/* parse type further */
|
|
if (tarhd.type==TAR_TYPE_DIR){
|
|
/* directory */
|
|
|
|
if (curdiskp==NULL){
|
|
/* on system level */
|
|
/* Note: no need to create disk, but must check if exists!!! */
|
|
if ((strncasecmp(dirnamebuf,"disk",4)==0)&&(strlen(dirnamebuf)>=5)){
|
|
i=atoi(dirnamebuf+4);
|
|
}else{
|
|
i=-1; /* invalid */
|
|
}
|
|
if ((i<0)||(i>=(int)disk_num)){
|
|
PRINTF_ERR("disk does not exist\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
}else if (curpartp==NULL){
|
|
/* on disk level */
|
|
/* Note: no need to create partition, but must check if exists!!! */
|
|
if (akai_find_part(curdiskp,dirnamebuf)==NULL){
|
|
PRINTF_ERR("partition does not exist\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
}else{
|
|
/* on partition level */
|
|
if (curpartp->type==PART_TYPE_DD){
|
|
/* harddisk DD partition */
|
|
PRINTF_ERR("no directory allowed in DD-partition\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
/* now, sampler partition */
|
|
if (curvolp!=NULL){ /* already in volume? */
|
|
PRINTF_ERR("no directory allowed in volume\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
/* load number */
|
|
lnum=AKAI_VOL_LNUM_OFF; /* default */
|
|
/* XXX use devminor field for load number */
|
|
sscanf(tarhd.devminor,"%o",&lnum);
|
|
/* Note: if sscanf finds nothing, lnum remains! */
|
|
/* correct lnum */
|
|
if ((lnum!=AKAI_VOL_LNUM_OFF)
|
|
&&((lnum<AKAI_VOL_LNUM_MIN)||(lnum>AKAI_VOL_LNUM_MAX))){
|
|
lnum=AKAI_VOL_LNUM_OFF; /* XXX default */
|
|
}
|
|
/* volume parameters */
|
|
parp=NULL; /* default volume parameters or keep old ones */
|
|
#ifndef TAR_NOVOLPARAMTARHD
|
|
/* XXX use linkname for volume parameters */
|
|
if ((tarhd.linkname[0]=='\0')&&(tarhd.linkname[1]=='P')){ /* XXX correct magic? */
|
|
parp=(struct akai_volparam_s *)(&tarhd.linkname[0]+2); /* XXX +2: linkname starts with magic */
|
|
}
|
|
#endif
|
|
/* check if destination volume already exists */
|
|
if (akai_find_vol(curpartp,&tmpvol,dirnamebuf)<0){
|
|
/* does not exist (or error in finding it, don't care) */
|
|
/* user-supplied volume type, Note: will be corrected below if bad or inactive */
|
|
vtype=vtype0;
|
|
if (vtype0==AKAI_VOL_TYPE_INACT){ /* no user-supplied type? */
|
|
/* XXX use devmajor field for type */
|
|
sscanf(tarhd.devmajor,"%o",&vtype);
|
|
/* Note: if sscanf finds nothing, vtype remains! */
|
|
/* correct vtype */
|
|
if (curpartp->type==PART_TYPE_HD9){
|
|
vtype=AKAI_VOL_TYPE_S900;
|
|
}else if ((vtype!=AKAI_VOL_TYPE_S1000)
|
|
&&(vtype!=AKAI_VOL_TYPE_S3000)
|
|
&&(vtype!=AKAI_VOL_TYPE_CD3000)){
|
|
vtype=AKAI_VOL_TYPE_S1000; /* XXX default */
|
|
}
|
|
}
|
|
|
|
/* create volume */
|
|
if (akai_create_vol(curpartp,&tmpvol,vtype,AKAI_CREATE_VOL_NOINDEX,dirnamebuf,lnum,parp)<0){
|
|
PRINTF_ERR("cannot create volume\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
}else{
|
|
/* volume already exists */
|
|
/* Note: keep volume type (even if user-supplied type) */
|
|
/* XXX use devminor field for load number */
|
|
if (tarhd.devminor[0]==0x00){ /* no load number? */
|
|
lnum=tmpvol.lnum; /* keep old value */
|
|
}
|
|
osver=tmpvol.osver; /* keep old value */
|
|
/* update load number and optional volume parameters */
|
|
if (akai_rename_vol(&tmpvol,NULL,lnum,osver,parp)<0){
|
|
PRINTF_ERR("cannot update volume\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
}
|
|
if ((tmpvol.param!=NULL)&&(parp!=NULL)&&verbose){
|
|
PRINTF_OUT("volume parameters imported\n");
|
|
FLUSH_ALL;
|
|
}
|
|
}
|
|
|
|
skip+=byteend; /* skip file */
|
|
continue; /* next */
|
|
}
|
|
/* now, regular file */
|
|
nlen=(u_int)strlen(dirnamebuf);
|
|
|
|
#ifndef TAR_NOTAGSFILE
|
|
/* handle tags-file */
|
|
if (strcmp(dirnamebuf,TAR_TAGSFILENAME)==0){
|
|
if ((curpartp!=NULL)&&(curpartp->type==PART_TYPE_HD)&&(curvolp==NULL)){ /* in S1000/S3000 harddisk partition on partition level? */
|
|
if (byteend==(4+AKAI_PARTHEAD_TAGNUM*AKAI_NAME_LEN)){ /* valid file size? (Note: tags magic and tag names) */
|
|
/* read tags-file into partition header */
|
|
if (READ(fd,(void *)curpartp->head.hd.tagsmagic,byteend)!=(int)byteend){
|
|
PRINTF_ERR("cannot read tags-file\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
/* XXX no check if valid tags magic */
|
|
/* write partition header */
|
|
if (akai_io_blks(curpartp,(u_char *)&curpartp->head.hd,
|
|
0,
|
|
AKAI_PARTHEAD_BLKS,
|
|
1,IO_BLKS_WRITE)<0){ /* 1: allocate cache if possible */
|
|
PRINTF_ERR("cannot write partition header\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
if (verbose){
|
|
PRINTF_OUT("tags imported\n");
|
|
FLUSH_ALL;
|
|
}
|
|
}else{
|
|
if (verbose){
|
|
PRINTF_OUT("invalid file size of tags-file, skipping file\n");
|
|
FLUSH_ALL;
|
|
}
|
|
skip+=byteend; /* skip file */
|
|
continue; /* next */
|
|
}
|
|
}else{
|
|
if (verbose){
|
|
PRINTF_OUT("tags-file must be on partition level of S1000/S3000 harddisk, skipping file\n");
|
|
FLUSH_ALL;
|
|
}
|
|
skip+=byteend; /* skip file */
|
|
continue; /* next */
|
|
}
|
|
continue; /* next */
|
|
}
|
|
#endif
|
|
#ifndef TAR_NOVOLPARAMFILE
|
|
/* handle volparam-file */
|
|
if (strcmp(dirnamebuf,TAR_VOLPARAMFILENAME)==0){
|
|
if ((curvolp!=NULL)&&(curvolp->param!=NULL)){ /* on volume level and volume has parameters? */
|
|
if (byteend==sizeof(struct akai_volparam_s)){ /* valid file size? */
|
|
/* read volparam-file into volume */
|
|
if (READ(fd,(void *)curvolp->param,byteend)!=(int)byteend){
|
|
PRINTF_ERR("cannot read volparam-file\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
/* update volume */
|
|
if (akai_rename_vol(curvolp,NULL,curvolp->lnum,curvolp->osver,curvolp->param)<0){
|
|
PRINTF_ERR("cannot update volume\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
if ((curvolp->param!=NULL)&&verbose){
|
|
PRINTF_OUT("volume parameters imported\n");
|
|
FLUSH_ALL;
|
|
}
|
|
}else{
|
|
if (verbose){
|
|
PRINTF_OUT("invalid file size of volparam-file, skipping file\n");
|
|
FLUSH_ALL;
|
|
}
|
|
skip+=byteend; /* skip file */
|
|
continue; /* next */
|
|
}
|
|
}else{
|
|
if (verbose){
|
|
if (curvolp==NULL){
|
|
PRINTF_OUT("volparam-file must be on volume level, skipping file\n");
|
|
}else{
|
|
PRINTF_OUT("volume has no parameters, skipping file\n");
|
|
}
|
|
FLUSH_ALL;
|
|
}
|
|
skip+=byteend; /* skip file */
|
|
continue; /* next */
|
|
}
|
|
continue; /* next */
|
|
}
|
|
#endif
|
|
#ifndef TAR_NOVOLINFO1FILE
|
|
#ifndef TAR_VOLINFO1FILENAME
|
|
#define TAR_VOLINFO1FILENAME "VOLINFO1.DAT"
|
|
#endif
|
|
#ifndef TAR_VOLINFO1FILE_SKIPB
|
|
#define TAR_VOLINFO1FILE_SKIPB 0x0010 /* number of bytes to skip in volinfo1-file */
|
|
#endif
|
|
/* handle volinfo1-file */
|
|
if (strcmp(dirnamebuf,TAR_VOLINFO1FILENAME)==0){
|
|
if ((curvolp!=NULL)&&(curvolp->param!=NULL)){ /* on volume level and volume has parameters? */
|
|
if (byteend==(TAR_VOLINFO1FILE_SKIPB+sizeof(struct akai_volparam_s))){ /* valid file size? */
|
|
if (LSEEK64(fd,(OFF64_T)TAR_VOLINFO1FILE_SKIPB,SEEK_CUR)<0){
|
|
PERROR("lseek");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
/* read volume parameters from volinfo1-file into volume */
|
|
l=sizeof(struct akai_volparam_s);
|
|
if (READ(fd,(void *)curvolp->param,l)!=(int)l){
|
|
PRINTF_ERR("cannot read volinfo1-file\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
/* update volume */
|
|
if (akai_rename_vol(curvolp,NULL,curvolp->lnum,curvolp->osver,curvolp->param)<0){
|
|
PRINTF_ERR("cannot update volume\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
if (verbose){
|
|
PRINTF_OUT("volume parameters imported\n");
|
|
FLUSH_ALL;
|
|
}
|
|
}else{
|
|
if (verbose){
|
|
PRINTF_OUT("invalid file size of volinfo1-file, skipping file\n");
|
|
FLUSH_ALL;
|
|
}
|
|
skip+=byteend; /* skip file */
|
|
continue; /* next */
|
|
}
|
|
}else{
|
|
if (verbose){
|
|
if (curvolp==NULL){
|
|
PRINTF_OUT("volinfo1-file must be on volume level, skipping file\n");
|
|
}else{
|
|
PRINTF_OUT("volume has no parameters, skipping file\n");
|
|
}
|
|
FLUSH_ALL;
|
|
}
|
|
skip+=byteend; /* skip file */
|
|
continue; /* next */
|
|
}
|
|
continue; /* next */
|
|
}
|
|
#endif
|
|
#ifndef TAR_NOSKIPDATFILE
|
|
/* skip dat-files */
|
|
if ((nlen>=4)&&(strncasecmp(dirnamebuf+nlen-4,".dat",4)==0)){
|
|
if (verbose){
|
|
PRINTF_OUT("skipping dat-file\n");
|
|
FLUSH_ALL;
|
|
}
|
|
skip+=byteend; /* skip file */
|
|
continue; /* next */
|
|
}
|
|
#endif
|
|
|
|
if (curpartp==NULL){
|
|
PRINTF_ERR("no files allowed on disk level\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
|
|
if (curpartp->type==PART_TYPE_DD){
|
|
/* harddisk DD partition */
|
|
|
|
/* import DD take */
|
|
|
|
if ((flags&TAR_IMPORT_WAV)&&(nlen>=4)&&(strncasecmp(dirnamebuf+nlen-4,".wav",4)==0)){
|
|
/* convert WAV file into DD take */
|
|
|
|
/* find free index */
|
|
for (ti=0;ti<AKAI_DDTAKE_MAXNUM;ti++){
|
|
/* take */
|
|
if (curpartp->head.dd.take[ti].stat==AKAI_DDTAKESTAT_FREE){ /* free? */
|
|
break; /* done */
|
|
}
|
|
}
|
|
if (ti==AKAI_DDTAKE_MAXNUM){ /* no free index? */
|
|
PRINTF_ERR("no free take index\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
|
|
/* Note: don't check if name already used, create new DD take */
|
|
wavret=akai_wav2take(fd,dirnamebuf,
|
|
curpartp,
|
|
ti,
|
|
&wavbcount,
|
|
0);
|
|
if ((wavret<0)||(byteend<wavbcount)){ /* error? */
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
skip+=byteend-wavbcount; /* skip unread rest */
|
|
continue; /* file done, next */
|
|
}
|
|
|
|
/* check file name */
|
|
if ((nlen<3)||(strcmp(dirnamebuf+nlen-3,AKAI_DDTAKE_FNAMEEND)!=0)){
|
|
PRINTF_ERR("invalid file name for DD take, skipping file\n");
|
|
skip+=byteend; /* skip file */
|
|
continue; /* next */
|
|
}
|
|
|
|
/* find free index */
|
|
for (ti=0;ti<AKAI_DDTAKE_MAXNUM;ti++){
|
|
/* take */
|
|
if (curpartp->head.dd.take[ti].stat==AKAI_DDTAKESTAT_FREE){ /* free? */
|
|
break; /* done */
|
|
}
|
|
}
|
|
if (ti==AKAI_DDTAKE_MAXNUM){ /* no free index? */
|
|
PRINTF_ERR("no free take index\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
|
|
/* get DD take header (DD directory entry) */
|
|
if (READ(fd,&t,sizeof(struct akai_ddtake_s))!=(int)sizeof(struct akai_ddtake_s)){
|
|
PRINTF_ERR("cannot read DD take header\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
|
|
/* get csizes (sample clusters) and csizee (envelope clusters) */
|
|
/* XXX use cstarts/cstarte fields in DD take header for csizes/csizee */
|
|
csizes=(t.cstarts[1]<<8)
|
|
+t.cstarts[0];
|
|
csizee=(t.cstarte[1]<<8)
|
|
+t.cstarte[0];
|
|
/* Note: akai_import_take() will increase csizee if required */
|
|
/* XXX preliminary check of csizes+csizee */
|
|
if ((csizes+csizee)*AKAI_DDPART_CBLKS>curpartp->bfree){
|
|
PRINTF_ERR("not enough space left\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
/* size in bytes */
|
|
tsize=sizeof(struct akai_ddtake_s)+(csizes+csizee)*AKAI_DDPART_CBLKS*AKAI_HD_BLOCKSIZE;
|
|
if (tsize>byteend){
|
|
PRINTF_ERR("inconsistent size\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
|
|
/* import take */
|
|
/* Note: akai_import_take() will increase csizee if required */
|
|
/* Note: akai_import_take() keeps name in DD take header */
|
|
/* Note: don't check if name already used, create new DD take */
|
|
if (akai_import_take(fd,curpartp,&t,ti,csizes,csizee)<0){
|
|
PRINTF_ERR("cannot import take\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
|
|
/* skip unread rest */
|
|
skip+=byteend-tsize;
|
|
continue; /* next */
|
|
}
|
|
|
|
/* now, sampler partition */
|
|
|
|
if (curvolp==NULL){ /* not in volume? */
|
|
PRINTF_ERR("files only allowed in volume\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
#if 0
|
|
skip+=byteend; /* skip file */
|
|
continue; /* next */
|
|
#endif
|
|
|
|
/* import file */
|
|
|
|
/* default osver */
|
|
osver=curvolp->osver; /* default: from volume */
|
|
if (vtype0==AKAI_VOL_TYPE_INACT){ /* no user-supplied type? */
|
|
/* XXX use devmajor field for osver */
|
|
sscanf(tarhd.devmajor,"%o",&osver);
|
|
}else if (vtype0==AKAI_VOL_TYPE_S900){
|
|
osver=0; /* non-compressed, akai_create_file() will correct osver if necessary */
|
|
}else if ((vtype0==AKAI_VOL_TYPE_S3000)||(vtype0==AKAI_VOL_TYPE_CD3000)){
|
|
osver=AKAI_OSVER_S3000MAX; /* XXX */
|
|
}else{
|
|
osver=AKAI_OSVER_S1000MAX; /* XXX */
|
|
}
|
|
/* Note: if sscanf finds nothing, osver remains! */
|
|
/* default tags */
|
|
tagp=NULL;
|
|
if ((curvolp->type==AKAI_VOL_TYPE_S3000)||(curvolp->type==AKAI_VOL_TYPE_CD3000)){
|
|
/* XXX use linkname for file tags */
|
|
if ((tarhd.linkname[0]=='\0')&&(tarhd.linkname[1]=='T')){ /* XXX correct magic? */
|
|
tagp=(u_char *)&tarhd.linkname[2];/* XXX +2: linkname starts with magic */
|
|
/* XXX no check for valid tag entries */
|
|
akai_sort_filetags(tagp);
|
|
}
|
|
}
|
|
|
|
if ((flags&TAR_IMPORT_WAV)&&(nlen>=4)&&(strncasecmp(dirnamebuf+nlen-4,".wav",4)==0)){
|
|
/* convert WAV file into sample file */
|
|
|
|
/* sample file type */
|
|
if (flags&(TAR_IMPORT_WAVS9|TAR_IMPORT_WAVS9C)){
|
|
/* S900 sample */
|
|
ftype=AKAI_SAMPLE900_FTYPE;
|
|
}else if (flags&TAR_IMPORT_WAVS1){
|
|
/* S1000 sample */
|
|
ftype=AKAI_SAMPLE1000_FTYPE;
|
|
}else if (flags&TAR_IMPORT_WAVS3){
|
|
/* S3000 sample */
|
|
ftype=AKAI_SAMPLE3000_FTYPE;
|
|
}else{
|
|
ftype=AKAI_FTYPE_FREE; /* invalid: derive sample file type from volume type/file osver */
|
|
/* Note: if S900 sample, use non-compressed sample format */
|
|
}
|
|
|
|
/* Note: akai_wav2sample() will correct osver if necessary */
|
|
wavret=akai_wav2sample(fd,dirnamebuf,
|
|
curvolp,
|
|
AKAI_CREATE_FILE_NOINDEX,
|
|
ftype,
|
|
(flags&TAR_IMPORT_WAVS9C)?1:0, /* if S900 sample, use compressed/non-compressed sample format */
|
|
osver,
|
|
tagp,
|
|
&wavbcount,
|
|
WAV2SAMPLE_OVERWRITE);
|
|
if ((wavret<0)||(byteend<wavbcount)){ /* error? */
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
skip+=byteend-wavbcount; /* skip unread rest */
|
|
continue; /* file done, next */
|
|
}
|
|
|
|
#if 1
|
|
{
|
|
static u_char anamebuf[AKAI_NAME_LEN+4+1]; /* +4 for ".<type>", +1 for '\0' */
|
|
u_int osver;
|
|
|
|
/* skip file with invalid name/type */
|
|
if (ascii2akai_filename(dirnamebuf,anamebuf,&osver,curvolp->type==AKAI_VOL_TYPE_S900)==AKAI_FTYPE_FREE){
|
|
if (verbose){
|
|
PRINTF_OUT("invalid file name/type, skipping file\n");
|
|
FLUSH_ALL;
|
|
}
|
|
skip+=byteend; /* skip file */
|
|
continue; /* next */
|
|
}
|
|
}
|
|
#endif
|
|
/* check if destination file already exists */
|
|
if (akai_find_file(curvolp,&tmpfile,dirnamebuf)==0){
|
|
/* exists */
|
|
/* delete file */
|
|
if (akai_delete_file(&tmpfile)<0){
|
|
PRINTF_ERR("cannot overwrite existing file\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
}
|
|
/* create destination file */
|
|
/* Note: akai_create_file() will correct osver if necessary */
|
|
if (akai_create_file(curvolp,
|
|
&tmpfile,
|
|
byteend,
|
|
AKAI_CREATE_FILE_NOINDEX,
|
|
dirnamebuf,
|
|
osver,
|
|
tagp)<0){
|
|
PRINTF_ERR("cannot create file\n");
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
/* import file */
|
|
if (akai_write_file(fd,NULL,&tmpfile,0,tmpfile.size)<0){
|
|
ret=-1;
|
|
goto tar_import_done;
|
|
}
|
|
if ((curvolp->type==AKAI_VOL_TYPE_S900)&&(tmpfile.osver!=0) /* compressed file in S900 volume? */
|
|
&&(osver==0)){ /* and supplied/determined osver is incompatible? */
|
|
/* update uncompr value */
|
|
akai_s900comprfile_updateuncompr(&tmpfile); /* ignore error */
|
|
}
|
|
#if 1
|
|
/* fix name in header (if necessary) */
|
|
akai_fixramname(&tmpfile); /* ignore error */
|
|
#endif
|
|
}
|
|
|
|
tar_import_done:
|
|
restore_curdir();
|
|
return ret;
|
|
}
|
|
|
|
|
|
|
|
/* EOF */
|