File: unbuffered_file.cc

package info (click to toggle)
zbackup 1.5-4
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 868 kB
  • sloc: cpp: 6,957; ansic: 468; python: 207; makefile: 10
file content (109 lines) | stat: -rw-r--r-- 2,396 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// Copyright (c) 2012-2014 Konstantin Isakov <ikm@zbackup.org> and ZBackup contributors, see CONTRIBUTORS
// Part of ZBackup. Licensed under GNU GPLv2 or later + OpenSSL, see LICENSE

#define _LARGEFILE64_SOURCE

#include <fcntl.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

#include "check.hh"
#include "unbuffered_file.hh"


#if defined( __APPLE__ ) || defined( __OpenBSD__ ) || defined(__FreeBSD__) || defined(__CYGWIN__)
#define lseek64 lseek
#endif


UnbufferedFile::UnbufferedFile( char const * fileName, Mode mode )
{

  int flags = ( mode == ReadWrite ? ( O_RDWR | O_CREAT ) :
     ( mode == WriteOnly ? ( O_WRONLY | O_CREAT | O_TRUNC ) : O_RDONLY ) );
#if !defined( __APPLE__ ) && !defined( __OpenBSD__ ) && !defined(__FreeBSD__) && !defined(__CYGWIN__)
  flags |= O_LARGEFILE;
#endif
  fd = open( fileName, flags, 0666 );
  if ( fd < 0 )
    throw exCantOpen( fileName );
}

size_t UnbufferedFile::read( void * buf, size_t size )
{
  char * next = ( char * ) buf;
  size_t left = size;

  while( left )
  {
    ssize_t rd = ::read( fd, next, left );
    if ( rd < 0 )
    {
      if ( errno != EINTR )
        throw exReadError();
    }
    else
    if ( rd > 0 )
    {
      CHECK( ( size_t ) rd <= left, "read too many bytes from a file" );
      next += rd;
      left -= rd;
    }
    else
      break;
  }

  return size - left;
}

void UnbufferedFile::write( void const * buf, size_t size )
{
  char const * next = ( char const * ) buf;
  size_t left = size;

  while( left )
  {
    ssize_t written = ::write( fd, next, left );
    if ( written < 0 )
    {
      if ( errno != EINTR )
        throw exWriteError();
    }
    else
    {
      CHECK( ( size_t ) written <= left, "wrote too many bytes to a file" );
      next += written;
      left -= written;
    }
  }
}

UnbufferedFile::Offset UnbufferedFile::size()
{
  Offset cur = lseek64( fd, 0, SEEK_CUR );
  if ( cur < 0 )
    throw exSeekError();
  Offset result = lseek64( fd, 0, SEEK_END );
  if ( result < 0 || lseek64( fd, cur, SEEK_SET ) < 0 )
    throw exSeekError();
  return result;
}

void UnbufferedFile::seekCur( Offset offset )
{
  if ( lseek64( fd, offset, SEEK_CUR ) < 0 )
    throw exSeekError();
}

void UnbufferedFile::seek( Offset offset )
{
  if ( lseek64( fd, offset, SEEK_SET ) < 0 )
    throw exSeekError();
}

UnbufferedFile::~UnbufferedFile()
{
  close( fd );
}