virtual-backup.c
author nathan
Sat, 29 Dec 2007 15:28:22 +0100
branchtrunk
changeset 9 d6649fe2a4e0
parent 6 6262df5a6216
child 15 a9348bf5f6e7
permissions -rw-r--r--
Added tag 0.7.0 for changeset a306b5e43b44
nathan@4
     1
/* virtual-backup.c
nathan@4
     2
Copyright (c) 2000-2004 Craig Condit, Stefan Hülswitt.
nathan@4
     3
nathan@4
     4
Redistribution and use in source and binary forms, with or without
nathan@4
     5
modification, are permitted provided that the following conditions are met: 
nathan@4
     6
nathan@4
     7
1. Redistributions of source code must retain the above copyright notice,
nathan@4
     8
   this list of conditions and the following disclaimer. 
nathan@4
     9
2. Redistributions in binary form must reproduce the above copyright notice,
nathan@4
    10
   this list of conditions and the following disclaimer in the documentation
nathan@4
    11
   and/or other materials provided with the distribution. 
nathan@4
    12
nathan@4
    13
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
nathan@4
    14
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
nathan@4
    15
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
nathan@4
    16
DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
nathan@4
    17
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
nathan@4
    18
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
nathan@4
    19
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
nathan@4
    20
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
nathan@4
    21
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
nathan@4
    22
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
nathan@4
    23
SUCH DAMAGE.
nathan@4
    24
*/
nathan@4
    25
nathan@4
    26
#define _LARGEFILE64_SOURCE
nathan@4
    27
#define _GNU_SOURCE
nathan@4
    28
nathan@4
    29
#include <stdlib.h>
nathan@4
    30
#include <stdio.h>
nathan@4
    31
#include <unistd.h>
nathan@4
    32
#include <fcntl.h>
nathan@4
    33
#include <errno.h>
nathan@4
    34
#include <string.h>
nathan@4
    35
#include <sys/wait.h>
nathan@4
    36
#include <sys/stat.h>
nathan@4
    37
nathan@4
    38
#include "virtual.h"
nathan@4
    39
#include "cdbackup.h"
nathan@4
    40
#include "cdrom.h"
nathan@4
    41
#include "misc.h"
nathan@4
    42
#include "debug.h"
nathan@4
    43
nathan@4
    44
//#define DEBUGOUT
nathan@4
    45
nathan@4
    46
extern int virtual, multi;
nathan@4
    47
nathan@4
    48
extern int fd;
nathan@4
    49
extern struct virt_header *virt_header;
nathan@4
    50
extern int virtualMissing;
nathan@4
    51
extern char *real_virt_name;
nathan@4
    52
nathan@4
    53
#ifndef DEBUGOUT
nathan@4
    54
static pid_t childpid;
nathan@4
    55
#endif
nathan@4
    56
static int vfd=-1;
nathan@4
    57
nathan@4
    58
/****************************************************************************/
nathan@4
    59
nathan@4
    60
void VnewTrack(void)
nathan@4
    61
{
nathan@4
    62
  if(virtual) {
nathan@4
    63
    long long pos;
nathan@4
    64
    if(virtualMissing) {
nathan@4
    65
      if((fd=open64(real_virt_name,O_RDWR|O_CREAT,S_IRUSR|S_IWUSR|S_IRGRP| S_IROTH))<0) error("Open failed (new track)");
nathan@4
    66
      if(write(fd,virt_header,CD_FRAMESIZE)!=CD_FRAMESIZE) error("Write failed (new track)");
nathan@4
    67
      virtualMissing=0;
nathan@4
    68
      }
nathan@4
    69
    if(virt_header->tracks>=MAX_VIRT_TRACKS-1) serror("Maximum number of virtual tracks reached");
nathan@6
    70
    pos=(long long)(virt_header->start[virt_header->tracks]=virt_header->leadout)*CD_FRAMESIZE;
nathan@4
    71
    virt_header->tracks++;
nathan@4
    72
    if(lseek64(fd,pos,SEEK_SET)<0) error("Seek failed (new track)");
nathan@4
    73
    }
nathan@4
    74
  else {
nathan@4
    75
#ifndef DEBUGOUT
nathan@4
    76
    int pd[2];
nathan@4
    77
    Vclose();
nathan@4
    78
    if(pipe(pd)<0) error("Pipe failed (new track)");
nathan@4
    79
    if((childpid=fork())<0) error("Fork failed (new track)");
nathan@4
    80
    if(childpid==0) { /* child */
nathan@4
    81
      close(pd[1]);
nathan@4
    82
      close(0);
nathan@4
    83
      dup2(pd[0],0);
nathan@4
    84
      start_cdrecord(); /* doesn't returns */
nathan@4
    85
      }
nathan@4
    86
    close(pd[0]); fd=pd[1];
nathan@4
    87
#else
nathan@4
    88
    /* debug code; send data to /dev/null. */
nathan@4
    89
    Vclose();
nathan@4
    90
    fprintf(stderr,"DEBUG CODE: NO recording, sending data to /dev/null!\n");
nathan@4
    91
    if((fd=open("/dev/null",O_WRONLY))<0) error("Open failed (/dev/null)");
nathan@4
    92
#endif
nathan@4
    93
    cd_avail-=padsize*CD_FRAMESIZE;
nathan@4
    94
    }
nathan@4
    95
}
nathan@4
    96
nathan@4
    97
/****************************************************************************/
nathan@4
    98
nathan@4
    99
int Vsize(void)
nathan@4
   100
{
nathan@4
   101
  return virt_header->leadout;
nathan@4
   102
}
nathan@4
   103
nathan@4
   104
/****************************************************************************/
nathan@4
   105
nathan@4
   106
int VhasCont(void)
nathan@4
   107
{
nathan@4
   108
  return virt_header->has_cont;
nathan@4
   109
}
nathan@4
   110
nathan@4
   111
/****************************************************************************/
nathan@4
   112
nathan@4
   113
void VprepareDump(void)
nathan@4
   114
{
nathan@4
   115
  if((vfd=dup(fd))<0) error("Dup failed");
nathan@4
   116
  Vclose();
nathan@4
   117
}
nathan@4
   118
nathan@4
   119
/****************************************************************************/
nathan@4
   120
nathan@4
   121
void VvirtRead(void *buf)
nathan@4
   122
{
nathan@4
   123
  if(full_read(vfd,buf,CD_FRAMESIZE)!=CD_FRAMESIZE)
nathan@4
   124
    serror("Unexpected EOF reading data");
nathan@4
   125
}
nathan@4
   126
nathan@4
   127
/****************************************************************************/
nathan@4
   128
nathan@4
   129
void VcloseTrack(int cont)
nathan@4
   130
{
nathan@4
   131
  if(virtual) {
nathan@4
   132
    if(lseek64(fd,0,SEEK_SET)<0) error("Seek failed (close track)");
nathan@4
   133
    virt_header->has_cont=cont;
nathan@4
   134
    if(write(fd,virt_header,CD_FRAMESIZE)!=CD_FRAMESIZE) error("Write failed (close track)");
nathan@4
   135
    Vclose();
nathan@4
   136
    }
nathan@4
   137
  else {
nathan@4
   138
    Vclose();
nathan@4
   139
#ifndef DEBUGOUT
nathan@4
   140
    DEBUG("VcloseTrack: waiting for child termination\n");
nathan@4
   141
    while(wait(0)!=childpid);
nathan@4
   142
#endif
nathan@4
   143
    }
nathan@4
   144
  if(vfd>=0) { close(vfd); vfd=-1; }
nathan@4
   145
}
nathan@4
   146
nathan@4
   147
/****************************************************************************/
nathan@4
   148
nathan@4
   149
void Vwrite(const void *buf)
nathan@4
   150
{
nathan@4
   151
  if(write(fd,buf,CD_FRAMESIZE)!=CD_FRAMESIZE) error("Write failed");
nathan@4
   152
  if(virtual) virt_header->leadout++;
nathan@4
   153
  cd_avail-=CD_FRAMESIZE;
nathan@4
   154
}