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)
57
volatile CSFile *fh = NULL;
60
fh = openFile(mode | CSFile::CREATE); // success, do not try again.
63
if (retry || !CSFile::isDirNotFound(&self->myException))
66
/* Make sure the parent directory exists: */
67
CSPath *dir = CSPath::newPath(RETAIN(this), "..");
77
CSFile *CSPath::createFile(int mode)
83
while (file == NULL) {
84
file = try_CreateAndOpen(self, mode, retry);
90
/* Copy the contents of one file to another.
91
* The destination need not exist.
92
* If the destination exists, it will be
93
* overwritten if 'overwrite' is true.
95
void CSPath::copyFile(CSPath *in_to_file, bool overwrite)
97
CSPath *to_file = in_to_file;
99
CSFile *infile, *outfile;
104
if (to_file->exists(&is_dir)) {
106
to_file = CSPath::newPath(RETAIN(in_to_file), getNameCString());
109
if (to_file->exists(&is_dir)) {
111
CSException::throwFileError(CS_CONTEXT, to_file->getCString(), EEXIST);
116
CSException::throwFileError(CS_CONTEXT, to_file->getCString(), EEXIST);
119
infile = openFile(CSFile::READONLY);
122
outfile = to_file->createFile(CSFile::TRUNCATE);
125
CSStream::pipe(outfile->getOutputStream(), infile->getInputStream());
129
if (to_file != in_to_file)
132
release_(in_to_file);
136
void CSPath::makePath()
142
if (iPath->length() <= 1)
145
if (exists(&is_dir)) {
147
CSException::throwFileError(CS_CONTEXT, iPath, EEXIST);
151
path = CSPath::newPath(RETAIN(this), "..");
162
/* Copy the contents of one directory to another.
163
* The destination must be a directory.
164
* The new source directory will be copied to
165
* a directory of the same name in the destination.
167
void CSPath::copyDir(CSPath *in_to_dir, bool overwrite)
169
CSPath *to_dir = in_to_dir;
171
CSDirectory *dir = NULL;
177
if (to_dir->exists(&is_dir)) {
179
CSException::throwFileError(CS_CONTEXT, to_dir->getCString(), ENOTDIR);
180
/* Add the source directory name to the destination: */
181
to_dir = CSPath::newPath(RETAIN(in_to_dir), getNameCString());
184
if (to_dir->exists(&is_dir)) {
186
CSException::throwFileError(CS_CONTEXT, to_dir->getCString(), EEXIST);
191
/* Make the directory and copy the contents of the source
196
dir = openDirectory();
198
while (dir->next()) {
200
path = CSPath::newPath(RETAIN(this), dir->name());
203
path->copyFile(RETAIN(to_dir), overwrite);
205
path->copyDir(RETAIN(to_dir), overwrite);
210
if (to_dir != in_to_dir)
219
bool CSPath::isLink()
224
link = sys_isLink(iPath->getCString());
229
bool CSPath::isEmpty()
231
CSDirectory *dir = NULL;
232
bool is_dir, result = true;
235
if (!exists(&is_dir))
241
dir = openDirectory();
251
void CSPath::emptyDir()
258
if (!exists(&is_dir))
262
CSException::throwFileError(CS_CONTEXT, iPath, ENOTDIR);
264
dir = openDirectory();
267
while (dir->next()) {
268
path = CSPath::newPath(RETAIN(this), dir->name());
281
void CSPath::emptyPath()
288
if (!exists(&is_dir))
292
CSException::throwFileError(CS_CONTEXT, iPath, ENOTDIR);
294
dir = openDirectory();
297
while (dir->next()) {
298
path = CSPath::newPath(RETAIN(this), dir->name());
311
void CSPath::copyTo(CSPath *to_path, bool overwrite)
317
if (!exists(&is_dir))
318
CSException::throwFileError(CS_CONTEXT, iPath, ENOENT);
322
/* The source is a directory. */
323
copyDir(to_path, overwrite);
325
/* The source is not a directory: */
326
copyFile(to_path, overwrite);
332
void CSPath::moveTo(CSPath *in_to_path)
334
CSPath *to_path = NULL;
341
CSException::throwFileError(CS_CONTEXT, iPath, ENOENT);
343
if (in_to_path->exists(&is_dir)) {
345
to_path = CSPath::newPath(RETAIN(in_to_path), getNameCString());
347
if (to_path->exists(NULL))
348
CSException::throwFileError(CS_CONTEXT, to_path->getCString(), EEXIST);
352
CSException::throwFileError(CS_CONTEXT, to_path->getCString(), ENOTDIR);
354
to_path = RETAIN(in_to_path);
358
release_(in_to_path);
362
void CSPath::remove()
366
if (exists(&is_dir)) {
377
void CSPath::touch(bool create_path)
383
file = createFile(CSFile::READONLY);
385
file = openFile(CSFile::READONLY | CSFile::CREATE);
390
CSString *CSPath::getString()
395
const char *CSPath::getCString()
397
return iPath->getCString();
400
const char *CSPath::getNameCString()
402
const char *str = getCString();
404
return cs_last_name_of_path(str);
407
off64_t CSPath::getSize(const char *path)
411
info(path, NULL, &size, NULL);
415
off64_t CSPath::getSize()
419
info((bool *) NULL, &size, (CSTime *) NULL);
427
info(&is_dir, (off64_t *) NULL, (CSTime *) NULL);
431
bool CSPath::exists(bool *is_dir)
433
if (!sys_exists(iPath->getCString()))
441
void CSPath::info(const char *path, bool *is_dir, off64_t *size, CSTime *mod_time)
443
sys_stat(path, is_dir, size, mod_time);
447
void CSPath::info(bool *is_dir, off64_t *size, CSTime *mod_time)
449
info(iPath->getCString(), is_dir, size, mod_time);
452
CSFile *CSPath::openFile(int mode)
457
file = CSFile::newFile(RETAIN(this));
464
void CSPath::removeFile()
466
sys_removeFile(iPath->getCString());
469
void CSPath::makeDir()
473
cs_strcpy(PATH_MAX, path, iPath->getCString());
474
cs_remove_dir_char(path);
479
CSDirectory *CSPath::openDirectory()
484
dir = CSDirectory::newDirectory(RETAIN(this));
491
void CSPath::removeDir()
494
sys_removeDir(iPath->getCString());
497
void CSPath::rename(const char *name)
499
char new_path[PATH_MAX];
500
CSString *tmp_path, *old_path = iPath;
504
cs_strcpy(PATH_MAX, new_path, iPath->getCString());
505
cs_remove_last_name_of_path(new_path);
506
cs_add_dir_char(PATH_MAX, new_path);
507
cs_strcat(PATH_MAX, new_path, name);
509
lock_(&iRename_lock); // protect against race condition when testing if the new name exists yet or not.
510
if (sys_exists(new_path))
511
CSException::throwFileError(CS_CONTEXT, new_path, EEXIST);
513
tmp_path = CSString::newString(new_path);
516
sys_rename(iPath->getCString(), new_path);
519
unlock_(&iRename_lock);
528
void CSPath::move(CSPath *to_path)
532
lock_(&iRename_lock); // protect against race condition when testing if the new name exists yet or not.
533
if (to_path->exists())
534
CSException::throwFileError(CS_CONTEXT, to_path->getCString(), EEXIST);
536
/* Cannot move from TD to non-TD: */
537
sys_rename(iPath->getCString(), to_path->getCString());
538
unlock_(&iRename_lock);
543
CSPath *CSPath::getCWD()
547
sys_getcwd(path, PATH_MAX);
548
return newPath(path);
551
CSPath *CSPath::newPath(const char *path)
554
CSException::throwAssertion(CS_CONTEXT, "Initial string may not be NULL");
555
return newPath(CSString::newString(path));
558
CSPath *CSPath::newPath(CSString *path)
566
/* Adjust the path string so that it does not have
567
* a terminating CS_DIR_CHAR:
569
if (path->endsWith(CS_DIR_DELIM) && path->length() > 1) {
570
p->iPath = path->left(CS_DIR_DELIM, -1);
579
CSPath *CSPath::newPath(CSPath *cwd, const char *path)
581
char abs_path[PATH_MAX];
584
cs_make_absolute_path(PATH_MAX, abs_path, path, cwd->getCString());
586
CSPath *p = newPath(abs_path);
590
CSPath *CSPath::newPath(CSString *cwd, const char *path)
592
char abs_path[PATH_MAX];
595
cs_make_absolute_path(PATH_MAX, abs_path, path, cwd->getCString());
597
CSPath *p = newPath(abs_path);
601
CSPath *CSPath::newPath(const char *cwd, CSString *path)
603
char abs_path[PATH_MAX];
606
cs_make_absolute_path(PATH_MAX, abs_path, path->getCString(), cwd);
608
CSPath *p = newPath(abs_path);
612
CSPath *CSPath::newPath(const char *cwd, const char *path)
614
char abs_path[PATH_MAX];
617
cs_make_absolute_path(PATH_MAX, abs_path, path, cwd);
618
CSPath *p = newPath(abs_path);