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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
* Original author: Paul McCullagh
20
* Continued development: Barry Leslie
25
* Basic file system path.
34
#include "CSStrUtil.h"
37
#include "CSDirectory.h"
42
* ---------------------------------------------------------------
45
CSLock CSPath::iRename_lock;
47
CSPath *CSPath::iCWD = NULL;
55
CSFile *CSPath::try_CreateAndOpen(CSThread *self, int mode, bool retry)
58
return openFile(mode | CSFile::CREATE); // success, do not try again.
61
if (retry || !CSFile::isDirNotFound(&self->myException))
64
/* Make sure the parent directory exists: */
65
CSPath *dir = CSPath::newPath(RETAIN(this), "..");
75
CSFile *CSPath::createFile(int mode)
81
while (file == NULL) {
82
file = try_CreateAndOpen(self, mode, retry);
88
/* Copy the contents of one file to another.
89
* The destination need not exist.
90
* If the destination exists, it will be
91
* overwritten if 'overwrite' is true.
93
void CSPath::copyFile(CSPath *in_to_file, bool overwrite)
95
CSPath *to_file = in_to_file;
97
CSFile *infile, *outfile;
102
if (to_file->exists(&is_dir)) {
104
to_file = CSPath::newPath(RETAIN(in_to_file), getNameCString());
107
if (to_file->exists(&is_dir)) {
109
CSException::throwFileError(CS_CONTEXT, to_file->getCString(), EEXIST);
114
CSException::throwFileError(CS_CONTEXT, to_file->getCString(), EEXIST);
117
infile = openFile(CSFile::READONLY);
120
outfile = to_file->createFile(CSFile::TRUNCATE);
123
CSStream::pipe(outfile->getOutputStream(), infile->getInputStream());
127
if (to_file != in_to_file)
130
release_(in_to_file);
134
void CSPath::makePath()
140
if (iPath->length() <= 1)
143
if (exists(&is_dir)) {
145
CSException::throwFileError(CS_CONTEXT, iPath, EEXIST);
149
path = CSPath::newPath(RETAIN(this), "..");
160
/* Copy the contents of one directory to another.
161
* The destination must be a directory.
162
* The new source directory will be copied to
163
* a directory of the same name in the destination.
165
void CSPath::copyDir(CSPath *in_to_dir, bool overwrite)
167
CSPath *to_dir = in_to_dir;
169
CSDirectory *dir = NULL;
175
if (to_dir->exists(&is_dir)) {
177
CSException::throwFileError(CS_CONTEXT, to_dir->getCString(), ENOTDIR);
178
/* Add the source directory name to the destination: */
179
to_dir = CSPath::newPath(RETAIN(in_to_dir), getNameCString());
182
if (to_dir->exists(&is_dir)) {
184
CSException::throwFileError(CS_CONTEXT, to_dir->getCString(), EEXIST);
189
/* Make the directory and copy the contents of the source
194
dir = openDirectory();
196
while (dir->next()) {
198
path = CSPath::newPath(RETAIN(this), dir->name());
201
path->copyFile(RETAIN(to_dir), overwrite);
203
path->copyDir(RETAIN(to_dir), overwrite);
208
if (to_dir != in_to_dir)
217
bool CSPath::isLink()
222
link = sys_isLink(iPath->getCString());
227
bool CSPath::isEmpty()
229
CSDirectory *dir = NULL;
230
bool is_dir, result = true;
233
if (!exists(&is_dir))
239
dir = openDirectory();
249
void CSPath::emptyDir()
256
if (!exists(&is_dir))
260
CSException::throwFileError(CS_CONTEXT, iPath, ENOTDIR);
262
dir = openDirectory();
265
while (dir->next()) {
266
path = CSPath::newPath(RETAIN(this), dir->name());
279
void CSPath::emptyPath()
286
if (!exists(&is_dir))
290
CSException::throwFileError(CS_CONTEXT, iPath, ENOTDIR);
292
dir = openDirectory();
295
while (dir->next()) {
296
path = CSPath::newPath(RETAIN(this), dir->name());
309
void CSPath::copyTo(CSPath *to_path, bool overwrite)
315
if (!exists(&is_dir))
316
CSException::throwFileError(CS_CONTEXT, iPath, ENOENT);
320
/* The source is a directory. */
321
copyDir(to_path, overwrite);
323
/* The source is not a directory: */
324
copyFile(to_path, overwrite);
330
void CSPath::moveTo(CSPath *in_to_path)
332
CSPath *to_path = NULL;
339
CSException::throwFileError(CS_CONTEXT, iPath, ENOENT);
341
if (in_to_path->exists(&is_dir)) {
343
to_path = CSPath::newPath(RETAIN(in_to_path), getNameCString());
345
if (to_path->exists(NULL))
346
CSException::throwFileError(CS_CONTEXT, to_path->getCString(), EEXIST);
350
CSException::throwFileError(CS_CONTEXT, to_path->getCString(), ENOTDIR);
352
to_path = RETAIN(in_to_path);
356
release_(in_to_path);
360
void CSPath::remove()
364
if (exists(&is_dir)) {
375
void CSPath::touch(bool create_path)
381
file = createFile(CSFile::READONLY);
383
file = openFile(CSFile::READONLY | CSFile::CREATE);
388
CSString *CSPath::getString()
393
const char *CSPath::getCString()
395
return iPath->getCString();
398
const char *CSPath::getNameCString()
400
const char *str = getCString();
402
return cs_last_name_of_path(str);
405
off64_t CSPath::getSize(const char *path)
409
info(path, NULL, &size, NULL);
413
off64_t CSPath::getSize()
417
info((bool *) NULL, &size, (CSTime *) NULL);
425
info(&is_dir, (off64_t *) NULL, (CSTime *) NULL);
429
bool CSPath::exists(bool *is_dir)
431
if (!sys_exists(iPath->getCString()))
439
void CSPath::info(const char *path, bool *is_dir, off64_t *size, CSTime *mod_time)
441
sys_stat(path, is_dir, size, mod_time);
445
void CSPath::info(bool *is_dir, off64_t *size, CSTime *mod_time)
447
info(iPath->getCString(), is_dir, size, mod_time);
450
CSFile *CSPath::openFile(int mode)
455
file = CSFile::newFile(RETAIN(this));
462
void CSPath::removeFile()
464
sys_removeFile(iPath->getCString());
467
void CSPath::makeDir()
471
cs_strcpy(PATH_MAX, path, iPath->getCString());
472
cs_remove_dir_char(path);
477
CSDirectory *CSPath::openDirectory()
482
dir = CSDirectory::newDirectory(RETAIN(this));
489
void CSPath::removeDir()
492
sys_removeDir(iPath->getCString());
495
void CSPath::rename(const char *name)
497
char new_path[PATH_MAX];
498
CSString *tmp_path, *old_path = iPath;
502
cs_strcpy(PATH_MAX, new_path, iPath->getCString());
503
cs_remove_last_name_of_path(new_path);
504
cs_add_dir_char(PATH_MAX, new_path);
505
cs_strcat(PATH_MAX, new_path, name);
507
lock_(&iRename_lock); // protect against race condition when testing if the new name exists yet or not.
508
if (sys_exists(new_path))
509
CSException::throwFileError(CS_CONTEXT, new_path, EEXIST);
511
tmp_path = CSString::newString(new_path);
514
sys_rename(iPath->getCString(), new_path);
517
unlock_(&iRename_lock);
526
void CSPath::move(CSPath *to_path)
529
lock_(&iRename_lock); // protect against race condition when testing if the new name exists yet or not.
530
if (to_path->exists())
531
CSException::throwFileError(CS_CONTEXT, to_path->getCString(), EEXIST);
533
/* Cannot move from TD to non-TD: */
534
sys_rename(iPath->getCString(), to_path->getCString());
535
unlock_(&iRename_lock);
539
CSPath *CSPath::getCWD()
543
sys_getcwd(path, PATH_MAX);
544
return newPath(path);
547
CSPath *CSPath::newPath(const char *path)
550
CSException::throwAssertion(CS_CONTEXT, "Initial string may not be NULL");
551
return newPath(CSString::newString(path));
554
CSPath *CSPath::newPath(CSString *path)
562
/* Adjust the path string so that it does not have
563
* a terminating CS_DIR_CHAR:
565
if (path->endsWith(CS_DIR_DELIM) && path->length() > 1) {
566
p->iPath = path->left(CS_DIR_DELIM, -1);
575
CSPath *CSPath::newPath(CSPath *cwd, const char *path)
577
char abs_path[PATH_MAX];
580
cs_make_absolute_path(PATH_MAX, abs_path, path, cwd->getCString());
582
CSPath *p = newPath(abs_path);
586
CSPath *CSPath::newPath(CSString *cwd, const char *path)
588
char abs_path[PATH_MAX];
591
cs_make_absolute_path(PATH_MAX, abs_path, path, cwd->getCString());
593
CSPath *p = newPath(abs_path);
597
CSPath *CSPath::newPath(const char *cwd, CSString *path)
599
char abs_path[PATH_MAX];
602
cs_make_absolute_path(PATH_MAX, abs_path, path->getCString(), cwd);
604
CSPath *p = newPath(abs_path);
608
CSPath *CSPath::newPath(const char *cwd, const char *path)
610
char abs_path[PATH_MAX];
613
cs_make_absolute_path(PATH_MAX, abs_path, path, cwd);
614
CSPath *p = newPath(abs_path);