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
41
static int unix_file_open(const char *path, int flags, mode_t mode)
43
return open(path, flags, mode);
46
int unix_file_close(int fh)
56
* ---------------------------------------------------------------
64
myFilePath->release();
67
CSOutputStream *CSFile::getOutputStream()
69
return CSFileOutputStream::newStream(RETAIN(this));
72
CSOutputStream *CSFile::getOutputStream(off_t offset)
74
return CSFileOutputStream::newStream(RETAIN(this), offset);
77
CSInputStream *CSFile::getInputStream()
79
return CSFileInputStream::newStream(RETAIN(this));
82
CSInputStream *CSFile::getInputStream(off_t offset)
84
return CSFileInputStream::newStream(RETAIN(this), offset);
87
void CSFile::open(int mode)
94
/* Create and open the file: */
101
if (retry || !isDirNotFound(&self->myException))
104
/* Make sure the parent directory exists: */
105
dir = CSPath::newPath(RETAIN(myFilePath), "..");
110
catch_(b) { /* Two threads may try to create the directory at the same time. */
111
if (!isDirExists(&self->myException))
128
bool CSFile::transfer(CSFile *dst_file, off_t dst_offset, CSFile *src_file, off_t src_offset, off_t size, char *buffer, size_t buffer_size)
133
if (size > (off_t) buffer_size)
136
tfer = (size_t) size;
137
if (!(tfer = src_file->read(buffer, src_offset, tfer, 0)))
139
dst_file->write(buffer, dst_offset, tfer);
148
#define CS_MASK ((S_IRUSR | S_IWUSR) | (S_IRGRP | S_IWGRP) | (S_IROTH))
153
unix_file_close(iFH);
158
off_t CSFile::getEOF()
162
if ((eof = lseek(iFH, 0, SEEK_END)) == -1)
163
CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
168
void CSFile::setEOF(off_t offset)
170
if (ftruncate(iFH, offset) == -1)
171
CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
174
size_t CSFile::read(void *data, off_t offset, size_t size, size_t min_size)
179
read_size = pread(iFH, data, size, offset);
182
CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
183
if ((size_t) read_size < min_size)
184
CSException::throwEOFError(CS_CONTEXT, myFilePath->getCString());
188
void CSFile::write(const void *data, off_t offset, size_t size)
193
write_size = pwrite(iFH, (void *) data, size, offset);
195
if (write_size != size)
196
CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
209
CSFile *CSFile::newFile(CSPath *path)
213
if (!(f = new CSFile())) {
215
CSException::throwOSError(CS_CONTEXT, ENOMEM);
217
f->myFilePath = path;
221
CSFile *CSFile::newFile(const char *path_str)
225
path = CSPath::newPath(path_str);
226
return newFile(path);
229
void CSFile::openFile(int mode)
241
if ((iFH = unix_file_open(myFilePath->getCString(), flags, CS_MASK)) == -1)
242
CSException::throwFileError(CS_CONTEXT, myFilePath->getCString(), errno);
244
/* Does not make sense to truncate, and have READONLY! */
245
if ((mode & TRUNCATE) && !(mode & READONLY))
250
* ---------------------------------------------------------------
251
* A READ BUFFERED FILE
254
CSReadBufferedFile::CSReadBufferedFile():
256
iFileBufferOffset(0),
261
CSReadBufferedFile::~CSReadBufferedFile()
270
void CSReadBufferedFile::close()
274
iFileBufferOffset = 0;
278
off_t CSReadBufferedFile::getEOF()
280
off_t eof = myFile->getEOF();
282
if (eof < iFileBufferOffset + iBufferDataLen)
283
return iFileBufferOffset + iBufferDataLen;
287
void CSReadBufferedFile::setEOF(off_t offset)
289
myFile->setEOF(offset);
290
if (offset < iFileBufferOffset) {
291
iFileBufferOffset = 0;
294
else if (offset < iFileBufferOffset + iBufferDataLen)
295
iBufferDataLen = offset - iFileBufferOffset;
298
size_t CSReadBufferedFile::read(void *data, off_t offset, size_t size, size_t min_size)
303
if (iBufferDataLen > 0) {
304
if (offset < iFileBufferOffset) {
306
if (offset + size > iFileBufferOffset + iBufferDataLen) {
307
// 6 (would have to do 2 reads and a memcpy (better is just one read)
311
if (offset + size > iFileBufferOffset) {
313
tfer = offset + size - iFileBufferOffset;
314
memcpy((char *) data + (iFileBufferOffset - offset), iFileBuffer, tfer);
317
// We assume we are reading back to front:
318
if (size < SC_DEFAULT_FILE_BUFFER_SIZE) {
321
if (offset + size >= SC_DEFAULT_FILE_BUFFER_SIZE) {
322
iFileBufferOffset = offset + size - SC_DEFAULT_FILE_BUFFER_SIZE;
323
mins = SC_DEFAULT_FILE_BUFFER_SIZE;
326
iFileBufferOffset = 0;
327
mins = (size_t) offset + size;
329
result = myFile->read(iFileBuffer, iFileBufferOffset, SC_DEFAULT_FILE_BUFFER_SIZE, mins);
330
iBufferDataLen = result;
331
memcpy(data, iFileBuffer + (offset - iFileBufferOffset), size);
334
result = myFile->read(data, offset, size, size);
337
if (offset + size <= iFileBufferOffset + iBufferDataLen) {
339
memcpy(data, iFileBuffer + (offset - iFileBufferOffset), size);
342
if (offset < iFileBufferOffset + iBufferDataLen) {
343
// 4 We assume we are reading front to back
344
tfer = iFileBufferOffset + iBufferDataLen - offset;
345
memcpy(data, iFileBuffer + (offset - iFileBufferOffset), tfer);
346
data = (char *) data + tfer;
349
if (min_size >= tfer)
358
if (size < SC_DEFAULT_FILE_BUFFER_SIZE) {
359
result = myFile->read(iFileBuffer, offset, SC_DEFAULT_FILE_BUFFER_SIZE, min_size);
360
iFileBufferOffset = offset;
361
iBufferDataLen = result;
364
memcpy(data, iFileBuffer, result);
367
result = myFile->read(data, offset, size, min_size);
368
return result + tfer;
371
void CSReadBufferedFile::write(const void *data, off_t offset, size_t size)
373
if (iBufferDataLen > 0) {
376
if (offset < iFileBufferOffset) {
378
if (offset + size > iFileBufferOffset + iBufferDataLen) {
379
// 6 (would have to do 2 reads and a memcpy (better is just one read)
380
memcpy((char *) data + (iFileBufferOffset - offset), iFileBuffer, iBufferDataLen);
382
else if (offset + size > iFileBufferOffset) {
384
tfer = offset + size - iFileBufferOffset;
385
memcpy(iFileBuffer, (char *) data + (iFileBufferOffset - offset), tfer);
388
else if (offset + size <= iFileBufferOffset + iBufferDataLen) {
390
memcpy(iFileBuffer + (offset - iFileBufferOffset), data, size);
392
else if (offset < iFileBufferOffset + iBufferDataLen) {
393
// 4 We assume we are reading front to back
394
tfer = iFileBufferOffset + iBufferDataLen - offset;
395
memcpy(iFileBuffer + (offset - iFileBufferOffset), data, tfer);
401
myFile->write(data, offset, size);
404
void CSReadBufferedFile::flush()
409
void CSReadBufferedFile::sync()
415
const char *CSReadBufferedFile::getEOL()
417
return myFile->getEOL();
420
void CSReadBufferedFile::openFile(int mode)
422
myFile->openFile(mode);
425
CSFile *CSReadBufferedFile::newFile(CSFile *file)
427
CSReadBufferedFile *f;
429
if (!(f = new CSReadBufferedFile())) {
431
CSException::throwOSError(CS_CONTEXT, ENOMEM);
434
f->myFilePath = file->myFilePath;
435
f->myFilePath->retain();
440
* ---------------------------------------------------------------
444
void CSBufferedFile::write(const void *data, off_t offset, size_t size)
446
if (iBufferDataLen > 0) {
447
if (offset < iFileBufferOffset && offset <= iFileBufferOffset + iBufferDataLen) {
450
tfer = iFileBufferOffset + SC_DEFAULT_FILE_BUFFER_SIZE - offset;
452
memcpy(iFileBuffer + (offset - iFileBufferOffset), data, size);
456
data = (char *) data + tfer;
462
if (size < SC_DEFAULT_FILE_BUFFER_SIZE) {
463
iFileBufferOffset = offset;
464
iBufferDataLen = size;
465
memcpy(iFileBuffer, data, size);
469
myFile->write(data, offset, size);
472
void CSBufferedFile::flush()
474
if (iBufferDirty && iBufferDataLen) {
475
myFile->write(iFileBuffer, iFileBufferOffset, iBufferDataLen);
476
iBufferDirty = false;
483
* ---------------------------------------------------------------
484
* FILE BASED ON THE STANDARD C FILE