1
/* Copyright (c) 2008 PrimeBase Technologies GmbH, Germany
3
* PrimeBase Media Stream for MySQL
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
* Original author: Paul McCullagh (H&G2JCtL)
20
* Continued development: Barry Leslie
46
static int unix_file_open(const char *path, int flags, mode_t mode)
48
return open(path, flags, mode);
51
int unix_file_close(int fh)
57
* ---------------------------------------------------------------
65
myFilePath->release();
68
CSOutputStream *CSFile::getOutputStream()
70
return CSFileOutputStream::newStream(RETAIN(this));
73
CSOutputStream *CSFile::getOutputStream(off64_t offset)
75
return CSFileOutputStream::newStream(RETAIN(this), offset);
78
CSInputStream *CSFile::getInputStream()
80
return CSFileInputStream::newStream(RETAIN(this));
83
CSInputStream *CSFile::getInputStream(off64_t offset)
85
return CSFileInputStream::newStream(RETAIN(this), offset);
88
void CSFile::open(int mode)
93
CLOBBER_PROTECT(retry);
97
/* Create and open the file: */
104
if (retry || !isDirNotFound(&self->myException))
107
/* Make sure the parent directory exists: */
108
dir = CSPath::newPath(RETAIN(myFilePath), "..");
113
catch_(b) { /* Two threads may try to create the directory at the same time. */
114
if (!isDirExists(&self->myException))
131
bool CSFile::transfer(CSFile *dst_file, off64_t dst_offset, CSFile *src_file, off64_t src_offset, off64_t size, char *buffer, size_t buffer_size)
136
if (size > (off64_t) buffer_size)
139
tfer = (size_t) size;
140
if (!(tfer = src_file->read(buffer, src_offset, tfer, 0)))
142
dst_file->write(buffer, dst_offset, tfer);
150
void CSFile::streamOut(CSOutputStream *dst_stream, off64_t src_offset, off64_t size, char *buffer, size_t buffer_size)
155
if (size > (off64_t) buffer_size)
158
tfer = (size_t) size;
160
read(buffer, src_offset, tfer, tfer);
161
dst_stream->write(buffer, tfer);
168
#define CS_MASK ((S_IRUSR | S_IWUSR) | (S_IRGRP | S_IWGRP) | (S_IROTH))
173
unix_file_close(iFH);
178
off64_t CSFile::getEOF()
182
if ((eof = lseek(iFH, 0, SEEK_END)) == (off64_t) -1)
183
CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
188
void CSFile::setEOF(off64_t offset)
190
if (ftruncate(iFH, offset) == -1)
191
CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
194
size_t CSFile::read(void *data, off64_t offset, size_t size, size_t min_size)
199
read_size = pread(iFH, data, size, offset);
202
CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
203
if ((size_t) read_size < min_size)
204
CSException::throwEOFError(CS_CONTEXT, myFilePath->getCString());
208
void CSFile::write(const void *data, off64_t offset, size_t size)
213
write_size = pwrite(iFH, (void *) data, size, offset);
215
if (write_size != size)
216
CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
229
CSFile *CSFile::newFile(CSPath *path)
233
if (!(f = new CSFile())) {
235
CSException::throwOSError(CS_CONTEXT, ENOMEM);
237
f->myFilePath = path;
241
CSFile *CSFile::newFile(const char *path_str)
245
path = CSPath::newPath(path_str);
246
return newFile(path);
249
void CSFile::openFile(int mode)
261
if ((iFH = unix_file_open(myFilePath->getCString(), flags, CS_MASK)) == -1)
262
CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
264
/* Does not make sense to truncate, and have READONLY! */
265
if ((mode & TRUNCATE) && !(mode & READONLY))
270
* ---------------------------------------------------------------
271
* A READ BUFFERED FILE
274
CSReadBufferedFile::CSReadBufferedFile():
276
iFileBufferOffset(0),
281
CSReadBufferedFile::~CSReadBufferedFile()
290
void CSReadBufferedFile::close()
294
iFileBufferOffset = 0;
298
off64_t CSReadBufferedFile::getEOF()
300
off64_t eof = myFile->getEOF();
302
if (eof < iFileBufferOffset + iBufferDataLen)
303
return iFileBufferOffset + iBufferDataLen;
307
void CSReadBufferedFile::setEOF(off64_t offset)
309
myFile->setEOF(offset);
310
if (offset < iFileBufferOffset) {
311
iFileBufferOffset = 0;
314
else if (offset < iFileBufferOffset + iBufferDataLen)
315
iBufferDataLen = offset - iFileBufferOffset;
318
size_t CSReadBufferedFile::read(void *data, off64_t offset, size_t size, size_t min_size)
323
if (iBufferDataLen > 0) {
324
if (offset < iFileBufferOffset) {
326
if (offset + size > iFileBufferOffset + iBufferDataLen) {
327
// 6 (would have to do 2 reads and a memcpy (better is just one read)
331
if (offset + size > iFileBufferOffset) {
333
tfer = offset + size - iFileBufferOffset;
334
memcpy((char *) data + (iFileBufferOffset - offset), iFileBuffer, tfer);
337
// We assume we are reading back to front:
338
if (size < SC_DEFAULT_FILE_BUFFER_SIZE) {
341
if (offset + size >= SC_DEFAULT_FILE_BUFFER_SIZE) {
342
iFileBufferOffset = offset + size - SC_DEFAULT_FILE_BUFFER_SIZE;
343
mins = SC_DEFAULT_FILE_BUFFER_SIZE;
346
iFileBufferOffset = 0;
347
mins = (size_t) offset + size;
349
result = myFile->read(iFileBuffer, iFileBufferOffset, SC_DEFAULT_FILE_BUFFER_SIZE, mins);
350
iBufferDataLen = result;
351
memcpy(data, iFileBuffer + (offset - iFileBufferOffset), size);
354
result = myFile->read(data, offset, size, size);
357
if (offset + size <= iFileBufferOffset + iBufferDataLen) {
359
memcpy(data, iFileBuffer + (offset - iFileBufferOffset), size);
362
if (offset < iFileBufferOffset + iBufferDataLen) {
363
// 4 We assume we are reading front to back
364
tfer = iFileBufferOffset + iBufferDataLen - offset;
365
memcpy(data, iFileBuffer + (offset - iFileBufferOffset), tfer);
366
data = (char *) data + tfer;
369
if (min_size >= tfer)
378
if (size < SC_DEFAULT_FILE_BUFFER_SIZE) {
379
result = myFile->read(iFileBuffer, offset, SC_DEFAULT_FILE_BUFFER_SIZE, min_size);
380
iFileBufferOffset = offset;
381
iBufferDataLen = result;
384
memcpy(data, iFileBuffer, result);
387
result = myFile->read(data, offset, size, min_size);
388
return result + tfer;
391
void CSReadBufferedFile::write(const void *data, off64_t offset, size_t size)
393
if (iBufferDataLen > 0) {
396
if (offset < iFileBufferOffset) {
398
if (offset + size > iFileBufferOffset + iBufferDataLen) {
399
// 6 (would have to do 2 reads and a memcpy (better is just one read)
400
memcpy((char *) data + (iFileBufferOffset - offset), iFileBuffer, iBufferDataLen);
402
else if (offset + size > iFileBufferOffset) {
404
tfer = offset + size - iFileBufferOffset;
405
memcpy(iFileBuffer, (char *) data + (iFileBufferOffset - offset), tfer);
408
else if (offset + size <= iFileBufferOffset + iBufferDataLen) {
410
memcpy(iFileBuffer + (offset - iFileBufferOffset), data, size);
412
else if (offset < iFileBufferOffset + iBufferDataLen) {
413
// 4 We assume we are reading front to back
414
tfer = iFileBufferOffset + iBufferDataLen - offset;
415
memcpy(iFileBuffer + (offset - iFileBufferOffset), data, tfer);
420
myFile->write(data, offset, size);
423
void CSReadBufferedFile::flush()
428
void CSReadBufferedFile::sync()
434
const char *CSReadBufferedFile::getEOL()
436
return myFile->getEOL();
439
void CSReadBufferedFile::openFile(int mode)
441
myFile->openFile(mode);
444
CSFile *CSReadBufferedFile::newFile(CSFile *file)
446
CSReadBufferedFile *f;
448
if (!(f = new CSReadBufferedFile())) {
450
CSException::throwOSError(CS_CONTEXT, ENOMEM);
453
f->myFilePath = file->myFilePath;
454
f->myFilePath->retain();
459
* ---------------------------------------------------------------
463
void CSBufferedFile::write(const void *data, off64_t offset, size_t size)
465
if (iBufferDataLen > 0) {
466
if (offset < iFileBufferOffset && offset <= iFileBufferOffset + iBufferDataLen) {
469
tfer = iFileBufferOffset + SC_DEFAULT_FILE_BUFFER_SIZE - offset;
471
memcpy(iFileBuffer + (offset - iFileBufferOffset), data, size);
474
data = (char *) data + tfer;
479
if (size < SC_DEFAULT_FILE_BUFFER_SIZE) {
480
iFileBufferOffset = offset;
481
iBufferDataLen = size;
482
memcpy(iFileBuffer, data, size);
486
myFile->write(data, offset, size);
489
void CSBufferedFile::flush()
491
if (iBufferDirty && iBufferDataLen) {
492
myFile->write(iFileBuffer, iFileBufferOffset, iBufferDataLen);
493
iBufferDirty = false;
500
* ---------------------------------------------------------------
501
* FILE BASED ON THE STANDARD C FILE