00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "CSConfig.h"
00030
00031 #include <string.h>
00032 #include <stdio.h>
00033
00034 #include "CSStrUtil.h"
00035 #include "CSSys.h"
00036 #include "CSFile.h"
00037 #include "CSDirectory.h"
00038 #include "CSPath.h"
00039 #include "CSGlobal.h"
00040
00041
00042
00043
00044
00045 CSLock CSPath::iRename_lock;
00046
00047 CSPath *CSPath::iCWD = NULL;
00048
00049 CSPath::~CSPath()
00050 {
00051 if (iPath)
00052 iPath->release();
00053 }
00054
00055 CSFile *CSPath::try_CreateAndOpen(CSThread *self, int mode, bool retry)
00056 {
00057 volatile CSFile *fh = NULL;
00058
00059 try_(a) {
00060 fh = openFile(mode | CSFile::CREATE);
00061 }
00062 catch_(a) {
00063 if (retry || !CSFile::isDirNotFound(&self->myException))
00064 throw_();
00065
00066
00067 CSPath *dir = CSPath::newPath(RETAIN(this), "..");
00068 push_(dir);
00069 dir->makePath();
00070 release_(dir);
00071
00072 }
00073 cont_(a);
00074 return (CSFile *) fh;
00075 }
00076
00077 CSFile *CSPath::createFile(int mode)
00078 {
00079 CSFile *file = NULL;
00080 bool retry = false;
00081
00082 enter_();
00083 while (file == NULL) {
00084 file = try_CreateAndOpen(self, mode, retry);
00085 retry = true;
00086 }
00087 return_(file);
00088 }
00089
00090
00091
00092
00093
00094
00095 void CSPath::copyFile(CSPath *in_to_file, bool overwrite)
00096 {
00097 CSPath *to_file = in_to_file;
00098 bool is_dir;
00099 CSFile *infile, *outfile;
00100
00101 enter_();
00102 push_(in_to_file);
00103
00104 if (to_file->exists(&is_dir)) {
00105 if (is_dir) {
00106 to_file = CSPath::newPath(RETAIN(in_to_file), getNameCString());
00107 push_(to_file);
00108
00109 if (to_file->exists(&is_dir)) {
00110 if (!overwrite)
00111 CSException::throwFileError(CS_CONTEXT, to_file->getCString(), EEXIST);
00112 to_file->remove();
00113 }
00114 }
00115 else if (!overwrite)
00116 CSException::throwFileError(CS_CONTEXT, to_file->getCString(), EEXIST);
00117 }
00118
00119 infile = openFile(CSFile::READONLY);
00120 push_(infile);
00121
00122 outfile = to_file->createFile(CSFile::TRUNCATE);
00123 push_(outfile);
00124
00125 CSStream::pipe(outfile->getOutputStream(), infile->getInputStream());
00126 release_(outfile);
00127 release_(infile);
00128
00129 if (to_file != in_to_file)
00130 release_(to_file);
00131
00132 release_(in_to_file);
00133 exit_();
00134 }
00135
00136 void CSPath::makePath()
00137 {
00138 CSPath *path;
00139 bool is_dir;
00140
00141 enter_();
00142 if (iPath->length() <= 1)
00143 exit_();
00144
00145 if (exists(&is_dir)) {
00146 if (!is_dir)
00147 CSException::throwFileError(CS_CONTEXT, iPath, EEXIST);
00148 exit_();
00149 }
00150
00151 path = CSPath::newPath(RETAIN(this), "..");
00152 push_(path);
00153
00154 path->makePath();
00155 makeDir();
00156
00157 release_(path);
00158
00159 exit_();
00160 }
00161
00162
00163
00164
00165
00166
00167 void CSPath::copyDir(CSPath *in_to_dir, bool overwrite)
00168 {
00169 CSPath *to_dir = in_to_dir;
00170 bool is_dir;
00171 CSDirectory *dir = NULL;
00172 CSPath *path = NULL;
00173
00174 enter_();
00175 push_(in_to_dir);
00176
00177 if (to_dir->exists(&is_dir)) {
00178 if (!is_dir)
00179 CSException::throwFileError(CS_CONTEXT, to_dir->getCString(), ENOTDIR);
00180
00181 to_dir = CSPath::newPath(RETAIN(in_to_dir), getNameCString());
00182 push_(to_dir);
00183
00184 if (to_dir->exists(&is_dir)) {
00185 if (!overwrite)
00186 CSException::throwFileError(CS_CONTEXT, to_dir->getCString(), EEXIST);
00187 to_dir->remove();
00188 }
00189 }
00190
00191
00192
00193
00194 to_dir->makePath();
00195
00196 dir = openDirectory();
00197 push_(dir);
00198 while (dir->next()) {
00199 self->interrupted();
00200 path = CSPath::newPath(RETAIN(this), dir->name());
00201 push_(path);
00202 if (dir->isFile())
00203 path->copyFile(RETAIN(to_dir), overwrite);
00204 else
00205 path->copyDir(RETAIN(to_dir), overwrite);
00206 release_(path);
00207 }
00208 release_(dir);
00209
00210 if (to_dir != in_to_dir)
00211 release_(to_dir);
00212
00213 release_(in_to_dir);
00214
00215 exit_();
00216 }
00217
00218
00219 bool CSPath::isLink()
00220 {
00221 bool link;
00222 enter_();
00223
00224 link = sys_isLink(iPath->getCString());
00225
00226 return_(link);
00227 }
00228
00229 bool CSPath::isEmpty()
00230 {
00231 CSDirectory *dir = NULL;
00232 bool is_dir, result = true;
00233
00234 enter_();
00235 if (!exists(&is_dir))
00236 return_(true);
00237
00238 if (!is_dir)
00239 return_(false);
00240
00241 dir = openDirectory();
00242 push_(dir);
00243
00244 if (dir->next())
00245 result = false;
00246
00247 release_(dir);
00248 return_(result);
00249 }
00250
00251 void CSPath::emptyDir()
00252 {
00253 CSDirectory *dir;
00254 CSPath *path = NULL;
00255 bool is_dir;
00256
00257 enter_();
00258 if (!exists(&is_dir))
00259 exit_();
00260
00261 if (!is_dir)
00262 CSException::throwFileError(CS_CONTEXT, iPath, ENOTDIR);
00263
00264 dir = openDirectory();
00265 push_(dir);
00266
00267 while (dir->next()) {
00268 path = CSPath::newPath(RETAIN(this), dir->name());
00269 push_(path);
00270 if (dir->isFile())
00271 path->remove();
00272 else
00273 path->removeDir();
00274 release_(path);
00275 }
00276
00277 release_(dir);
00278 exit_();
00279 }
00280
00281 void CSPath::emptyPath()
00282 {
00283 CSDirectory *dir;
00284 CSPath *path = NULL;
00285 bool is_dir;
00286
00287 enter_();
00288 if (!exists(&is_dir))
00289 exit_();
00290
00291 if (!is_dir)
00292 CSException::throwFileError(CS_CONTEXT, iPath, ENOTDIR);
00293
00294 dir = openDirectory();
00295 push_(dir);
00296
00297 while (dir->next()) {
00298 path = CSPath::newPath(RETAIN(this), dir->name());
00299 push_(path);
00300 if (dir->isFile())
00301 path->remove();
00302 else
00303 path->emptyPath();
00304 release_(path);
00305 }
00306
00307 release_(dir);
00308 exit_();
00309 }
00310
00311 void CSPath::copyTo(CSPath *to_path, bool overwrite)
00312 {
00313 bool is_dir;
00314
00315 enter_();
00316 push_(to_path);
00317 if (!exists(&is_dir))
00318 CSException::throwFileError(CS_CONTEXT, iPath, ENOENT);
00319
00320 pop_(to_path);
00321 if (is_dir)
00322
00323 copyDir(to_path, overwrite);
00324 else {
00325
00326 copyFile(to_path, overwrite);
00327 }
00328
00329 exit_();
00330 }
00331
00332 void CSPath::moveTo(CSPath *in_to_path)
00333 {
00334 CSPath *to_path = NULL;
00335 bool is_dir;
00336
00337 enter_();
00338 push_(in_to_path);
00339
00340 if (!exists(NULL))
00341 CSException::throwFileError(CS_CONTEXT, iPath, ENOENT);
00342
00343 if (in_to_path->exists(&is_dir)) {
00344 if (is_dir) {
00345 to_path = CSPath::newPath(RETAIN(in_to_path), getNameCString());
00346 push_(to_path);
00347 if (to_path->exists(NULL))
00348 CSException::throwFileError(CS_CONTEXT, to_path->getCString(), EEXIST);
00349 pop_(to_path);
00350 }
00351 else
00352 CSException::throwFileError(CS_CONTEXT, to_path->getCString(), ENOTDIR);
00353 } else
00354 to_path = RETAIN(in_to_path);
00355
00356 move(to_path);
00357
00358 release_(in_to_path);
00359 exit_();
00360 }
00361
00362 void CSPath::remove()
00363 {
00364 bool is_dir;
00365
00366 if (exists(&is_dir)) {
00367 if (is_dir) {
00368 emptyDir();
00369 removeDir();
00370 }
00371 else
00372 removeFile();
00373 }
00374 }
00375
00376
00377 void CSPath::touch(bool create_path)
00378 {
00379 CSFile *file;
00380
00381 enter_();
00382 if (create_path)
00383 file = createFile(CSFile::READONLY);
00384 else
00385 file = openFile(CSFile::READONLY | CSFile::CREATE);
00386 file->release();
00387 exit_();
00388 }
00389
00390 CSString *CSPath::getString()
00391 {
00392 return iPath;
00393 }
00394
00395 const char *CSPath::getCString()
00396 {
00397 return iPath->getCString();
00398 }
00399
00400 const char *CSPath::getNameCString()
00401 {
00402 const char *str = getCString();
00403
00404 return cs_last_name_of_path(str);
00405 }
00406
00407 off64_t CSPath::getSize(const char *path)
00408 {
00409 off64_t size;
00410
00411 info(path, NULL, &size, NULL);
00412 return size;
00413 }
00414
00415 off64_t CSPath::getSize()
00416 {
00417 off64_t size;
00418
00419 info((bool *) NULL, &size, (CSTime *) NULL);
00420 return size;
00421 }
00422
00423 bool CSPath::isDir()
00424 {
00425 bool is_dir;
00426
00427 info(&is_dir, (off64_t *) NULL, (CSTime *) NULL);
00428 return is_dir;
00429 }
00430
00431 bool CSPath::exists(bool *is_dir)
00432 {
00433 if (!sys_exists(iPath->getCString()))
00434 return false;
00435
00436 if (is_dir)
00437 *is_dir = isDir();
00438 return true;
00439 }
00440
00441 void CSPath::info(const char *path, bool *is_dir, off64_t *size, CSTime *mod_time)
00442 {
00443 sys_stat(path, is_dir, size, mod_time);
00444
00445 }
00446
00447 void CSPath::info(bool *is_dir, off64_t *size, CSTime *mod_time)
00448 {
00449 info(iPath->getCString(), is_dir, size, mod_time);
00450 }
00451
00452 CSFile *CSPath::openFile(int mode)
00453 {
00454 CSFile *file;
00455
00456 enter_();
00457 file = CSFile::newFile(RETAIN(this));
00458 push_(file);
00459 file->open(mode);
00460 pop_(file);
00461 return_(file);
00462 }
00463
00464 void CSPath::removeFile()
00465 {
00466 sys_removeFile(iPath->getCString());
00467 }
00468
00469 void CSPath::makeDir()
00470 {
00471 char path[PATH_MAX];
00472
00473 cs_strcpy(PATH_MAX, path, iPath->getCString());
00474 cs_remove_dir_char(path);
00475
00476 sys_makeDir(path);
00477 }
00478
00479 CSDirectory *CSPath::openDirectory()
00480 {
00481 CSDirectory *dir;
00482
00483 enter_();
00484 dir = CSDirectory::newDirectory(RETAIN(this));
00485 push_(dir);
00486 dir->open();
00487 pop_(dir);
00488 return_(dir);
00489 }
00490
00491 void CSPath::removeDir()
00492 {
00493 emptyDir();
00494 sys_removeDir(iPath->getCString());
00495 }
00496
00497 void CSPath::rename(const char *name)
00498 {
00499 char new_path[PATH_MAX];
00500 CSString *tmp_path, *old_path = iPath;
00501
00502 enter_();
00503
00504 cs_strcpy(PATH_MAX, new_path, iPath->getCString());
00505 cs_remove_last_name_of_path(new_path);
00506 cs_add_dir_char(PATH_MAX, new_path);
00507 cs_strcat(PATH_MAX, new_path, name);
00508
00509 lock_(&iRename_lock);
00510 if (sys_exists(new_path))
00511 CSException::throwFileError(CS_CONTEXT, new_path, EEXIST);
00512
00513 tmp_path = CSString::newString(new_path);
00514 push_(tmp_path);
00515
00516 sys_rename(iPath->getCString(), new_path);
00517
00518 pop_(tmp_path);
00519 unlock_(&iRename_lock);
00520
00521 old_path = iPath;
00522 iPath = tmp_path;
00523
00524 old_path->release();
00525 exit_();
00526 }
00527
00528 void CSPath::move(CSPath *to_path)
00529 {
00530 enter_();
00531 push_(to_path);
00532 lock_(&iRename_lock);
00533 if (to_path->exists())
00534 CSException::throwFileError(CS_CONTEXT, to_path->getCString(), EEXIST);
00535
00536
00537 sys_rename(iPath->getCString(), to_path->getCString());
00538 unlock_(&iRename_lock);
00539 release_(to_path);
00540 exit_();
00541 }
00542
00543 CSPath *CSPath::getCWD()
00544 {
00545 char path[PATH_MAX];
00546
00547 sys_getcwd(path, PATH_MAX);
00548 return newPath(path);
00549 }
00550
00551 CSPath *CSPath::newPath(const char *path)
00552 {
00553 if (!path)
00554 CSException::throwAssertion(CS_CONTEXT, "Initial string may not be NULL");
00555 return newPath(CSString::newString(path));
00556 }
00557
00558 CSPath *CSPath::newPath(CSString *path)
00559 {
00560 CSPath *p;
00561
00562 enter_();
00563 push_(path);
00564 new_(p, CSPath());
00565
00566
00567
00568
00569 if (path->endsWith(CS_DIR_DELIM) && path->length() > 1) {
00570 p->iPath = path->left(CS_DIR_DELIM, -1);
00571 path->release();
00572 }
00573 else
00574 p->iPath = path;
00575 pop_(path);
00576 return_(p);
00577 }
00578
00579 CSPath *CSPath::newPath(CSPath *cwd, const char *path)
00580 {
00581 char abs_path[PATH_MAX];
00582
00583 enter_();
00584 cs_make_absolute_path(PATH_MAX, abs_path, path, cwd->getCString());
00585 cwd->release();
00586 CSPath *p = newPath(abs_path);
00587 return_(p);
00588 }
00589
00590 CSPath *CSPath::newPath(CSString *cwd, const char *path)
00591 {
00592 char abs_path[PATH_MAX];
00593
00594 enter_();
00595 cs_make_absolute_path(PATH_MAX, abs_path, path, cwd->getCString());
00596 cwd->release();
00597 CSPath *p = newPath(abs_path);
00598 return_(p);
00599 }
00600
00601 CSPath *CSPath::newPath(const char *cwd, CSString *path)
00602 {
00603 char abs_path[PATH_MAX];
00604
00605 enter_();
00606 cs_make_absolute_path(PATH_MAX, abs_path, path->getCString(), cwd);
00607 path->release();
00608 CSPath *p = newPath(abs_path);
00609 return_(p);
00610 }
00611
00612 CSPath *CSPath::newPath(const char *cwd, const char *path)
00613 {
00614 char abs_path[PATH_MAX];
00615
00616 enter_();
00617 cs_make_absolute_path(PATH_MAX, abs_path, path, cwd);
00618 CSPath *p = newPath(abs_path);
00619 return_(p);
00620 }
00621