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
20
* Continued development: Barry Leslie
25
* Basic file system path.
33
#include <sys/param.h>
37
static int unix_file_rename(const char *from, const char *to)
39
return rename(from, to);
42
#include "CSStrUtil.h"
44
#include "CSDirectory.h"
49
* ---------------------------------------------------------------
53
CSPath *CSPath::iCWD = NULL;
61
CSFile *CSPath::createFile(int mode)
67
CLOBBER_PROTECT(retry);
70
/* Create and open the file: */
73
file = openFile(mode | CSFile::CREATE);
77
if (retry || !CSFile::isDirNotFound(&self->myException))
80
/* Make sure the parent directory exists: */
81
dir = CSPath::newPath(RETAIN(this), "..");
98
/* Copy the contents of one file to another.
99
* The destination need not exist.
100
* If the destination exists, it will be
101
* overwritten if 'overwrite' is true.
103
void CSPath::copyFile(CSPath *in_to_file, bool overwrite)
105
CSPath *to_file = in_to_file;
107
CSFile *infile, *outfile;
112
if (to_file->exists(&is_dir)) {
114
to_file = CSPath::newPath(RETAIN(in_to_file), getNameCString());
117
if (to_file->exists(&is_dir)) {
119
CSException::throwFileError(CS_CONTEXT, to_file->getCString(), EEXIST);
124
CSException::throwFileError(CS_CONTEXT, to_file->getCString(), EEXIST);
127
infile = openFile(CSFile::READONLY);
130
outfile = to_file->createFile(CSFile::TRUNCATE);
133
CSStream::pipe(outfile->getOutputStream(), infile->getInputStream());
137
if (to_file != in_to_file)
140
release_(in_to_file);
144
void CSPath::makePath()
150
if (iPath->length() <= 1)
153
if (exists(&is_dir)) {
155
CSException::throwFileError(CS_CONTEXT, iPath, EEXIST);
159
path = CSPath::newPath(RETAIN(this), "..");
167
finally_end_block(a);
171
/* Copy the contents of one directory to another.
172
* The destination must be a directory.
173
* The new source directory will be copied to
174
* a directory of the same name in the destination.
176
void CSPath::copyDir(CSPath *in_to_dir, bool overwrite)
178
CSPath *to_dir = in_to_dir;
180
CSDirectory *dir = NULL;
186
if (to_dir->exists(&is_dir)) {
188
CSException::throwFileError(CS_CONTEXT, to_dir->getCString(), ENOTDIR);
189
/* Add the source directory name to the destination: */
190
to_dir = CSPath::newPath(RETAIN(in_to_dir), getNameCString());
193
if (to_dir->exists(&is_dir)) {
195
CSException::throwFileError(CS_CONTEXT, to_dir->getCString(), EEXIST);
200
/* Make the directory and copy the contents of the source
205
dir = openDirectory();
207
while (dir->next()) {
209
path = CSPath::newPath(RETAIN(this), dir->name());
212
path->copyFile(RETAIN(to_dir), overwrite);
214
path->copyDir(RETAIN(to_dir), overwrite);
219
if (to_dir != in_to_dir)
228
bool CSPath::isLink()
233
if (lstat(iPath->getCString(), &sb) == -1)
234
CSException::throwFileError(CS_CONTEXT, iPath, errno);
236
return_(S_ISLNK(sb.st_mode));
239
bool CSPath::isEmpty()
241
CSDirectory *dir = NULL;
242
bool is_dir, result = true;
245
if (!exists(&is_dir))
251
dir = openDirectory();
259
finally_end_block(a);
263
void CSPath::emptyDir()
270
if (!exists(&is_dir))
274
CSException::throwFileError(CS_CONTEXT, iPath, ENOTDIR);
276
dir = openDirectory();
278
while (dir->next()) {
279
path = CSPath::newPath(RETAIN(this), dir->name());
293
finally_end_block(a);
297
void CSPath::copyTo(CSPath *to_path, bool overwrite)
303
if (!exists(&is_dir))
304
CSException::throwFileError(CS_CONTEXT, iPath, ENOENT);
308
/* The source is a directory. */
309
copyDir(to_path, overwrite);
311
/* The source is not a directory: */
312
copyFile(to_path, overwrite);
318
void CSPath::moveTo(CSPath *in_to_path)
320
CSPath *to_path = in_to_path;
325
CSException::throwFileError(CS_CONTEXT, iPath, ENOENT);
328
if (to_path->exists(&is_dir)) {
330
to_path = CSPath::newPath(RETAIN(in_to_path), getNameCString());
331
if (to_path->exists(NULL))
332
CSException::throwFileError(CS_CONTEXT, to_path->getCString(), EEXIST);
335
CSException::throwFileError(CS_CONTEXT, to_path->getCString(), ENOTDIR);
340
if (to_path != in_to_path)
343
finally_end_block(a);
348
void CSPath::remove()
352
if (exists(&is_dir)) {
363
void CSPath::touch(bool create_path)
369
file = createFile(CSFile::READONLY);
371
file = openFile(CSFile::READONLY | CSFile::CREATE);
376
CSString *CSPath::getString()
381
const char *CSPath::getCString()
383
return iPath->getCString();
386
const char *CSPath::getNameCString()
388
const char *str = getCString();
390
return cs_last_name_of_path(str);
393
off64_t CSPath::getSize()
397
info((bool *) NULL, &size, (CSTime *) NULL);
405
info(&is_dir, (off64_t *) NULL, (CSTime *) NULL);
410
* ---------------------------------------------------------------
414
bool CSPath::exists(bool *is_dir)
418
err = access(iPath->getCString(), F_OK);
426
void CSPath::info(bool *is_dir, off64_t *size, CSTime *mod_time)
430
if (stat(iPath->getCString(), &sb) == -1)
431
CSException::throwFileError(CS_CONTEXT, iPath, errno);
433
*is_dir = sb.st_mode & S_IFDIR;
438
/* This is the Linux version: */
439
mod_time->setUTC1970(sb.st_mtim.tv_sec, sb.st_mtim.tv_nsec);
441
mod_time->setUTC1970(sb.st_mtime, 0);
445
CSFile *CSPath::openFile(int mode)
450
file = CSFile::newFile(RETAIN(this));
457
void CSPath::removeFile()
459
if (unlink(iPath->getCString()) == -1) {
463
CSException::throwFileError(CS_CONTEXT, iPath, err);
467
static void cs_set_stats(char *path)
469
char super_path[PATH_MAX];
473
ptr = cs_last_name_of_path(path);
475
strcpy(super_path, ".");
477
cs_strcpy(PATH_MAX, super_path, path);
479
if ((ptr = cs_last_name_of_path(super_path)))
482
if (stat(super_path, &stats) == -1)
483
CSException::throwFileError(CS_CONTEXT, path, errno);
485
if (chmod(path, stats.st_mode) == -1)
486
CSException::throwFileError(CS_CONTEXT, path, errno);
488
/*chown(path, stats.st_uid, stats.st_gid);*/
491
void CSPath::makeDir()
495
cs_strcpy(PATH_MAX, path, iPath->getCString());
496
cs_remove_dir_char(path);
498
if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) == -1)
499
CSException::throwFileError(CS_CONTEXT, iPath, errno);
504
CSDirectory *CSPath::openDirectory()
509
dir = CSDirectory::newDirectory(RETAIN(this));
516
void CSPath::removeDir()
519
if (rmdir(iPath->getCString()) == -1) {
523
CSException::throwFileError(CS_CONTEXT, iPath, err);
527
void CSPath::rename(const char *name)
529
char new_path[PATH_MAX];
530
CSString *tmp_path, *old_path = iPath;
534
cs_strcpy(PATH_MAX, new_path, iPath->getCString());
535
cs_remove_last_name_of_path(new_path);
536
cs_add_dir_char(PATH_MAX, new_path);
537
cs_strcat(PATH_MAX, new_path, name);
539
tmp_path = CSString::newString(new_path);
542
if (unix_file_rename(iPath->getCString(), new_path) == -1)
543
CSException::throwFileError(CS_CONTEXT, iPath, errno);
553
void CSPath::move(CSPath *to_path)
555
/* Cannot move from TD to non-TD: */
556
if (unix_file_rename(iPath->getCString(), to_path->getCString()) == -1)
557
CSException::throwFileError(CS_CONTEXT, iPath, errno);
560
CSPath *CSPath::getCWD()
562
char path[MAXPATHLEN];
564
if (!getcwd(path, MAXPATHLEN))
565
CSException::throwOSError(CS_CONTEXT, errno);
567
return newPath(path);
570
CSPath *CSPath::newPath(const char *path)
573
CSException::throwAssertion(CS_CONTEXT, "Initial string may not be NULL");
574
return newPath(CSString::newString(path));
577
CSPath *CSPath::newPath(CSString *path)
585
/* Adjust the path string so that it does not have
586
* a terminating CS_DIR_CHAR:
588
if (path->endsWith(CS_DIR_DELIM) && path->length() > 1) {
589
p->iPath = path->left(CS_DIR_DELIM, -1);
598
CSPath *CSPath::newPath(CSPath *cwd, const char *path)
600
char abs_path[PATH_MAX];
603
cs_make_absolute_path(PATH_MAX, abs_path, path, cwd->getCString());
605
CSPath *p = newPath(abs_path);
609
CSPath *CSPath::newPath(CSString *cwd, const char *path)
611
char abs_path[PATH_MAX];
614
cs_make_absolute_path(PATH_MAX, abs_path, path, cwd->getCString());
616
CSPath *p = newPath(abs_path);
620
CSPath *CSPath::newPath(const char *cwd, CSString *path)
622
char abs_path[PATH_MAX];
625
cs_make_absolute_path(PATH_MAX, abs_path, path->getCString(), cwd);
627
CSPath *p = newPath(abs_path);
631
CSPath *CSPath::newPath(const char *cwd, const char *path)
633
char abs_path[PATH_MAX];
636
cs_make_absolute_path(PATH_MAX, abs_path, path, cwd);
637
CSPath *p = newPath(abs_path);