~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/pbms/src/cslib/CSPath.cc

  • Committer: Barry.Leslie at PrimeBase
  • Date: 2010-10-18 21:21:20 UTC
  • mto: This revision was merged to the branch mainline in revision 1871.
  • Revision ID: barry.leslie@primebase.com-20101018212120-dqukgtkwhb1imt1o
Merged changes from lp:pbms. These changes should remove any danger
of longjmp() clobbering local variables.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
 
29
29
#include "CSConfig.h"
30
30
 
31
 
#include <unistd.h>
32
 
#include <sys/stat.h>
33
 
#include <sys/param.h>
34
31
#include <string.h>
35
32
#include <stdio.h>
36
33
 
37
 
static int unix_file_rename(const char *from, const char *to)
38
 
{
39
 
        return rename(from, to);
40
 
}
41
 
 
42
34
#include "CSStrUtil.h"
 
35
#include "CSSys.h"
43
36
#include "CSFile.h"
44
37
#include "CSDirectory.h"
45
38
#include "CSPath.h"
49
42
 * ---------------------------------------------------------------
50
43
 * CORE SYSTEM PATH
51
44
 */
 
45
CSLock  CSPath::iRename_lock;
52
46
 
53
47
CSPath *CSPath::iCWD = NULL;
54
48
 
58
52
                iPath->release();
59
53
}
60
54
 
 
55
CSFile *CSPath::try_CreateAndOpen(CSThread *self, int mode, bool retry)
 
56
{
 
57
        try_(a) {
 
58
                return openFile(mode | CSFile::CREATE); // success, do not try again.
 
59
        }
 
60
        catch_(a) {
 
61
                if (retry || !CSFile::isDirNotFound(&self->myException))
 
62
                        throw_();
 
63
 
 
64
                /* Make sure the parent directory exists: */
 
65
                CSPath  *dir = CSPath::newPath(RETAIN(this), "..");
 
66
                push_(dir);
 
67
                dir->makePath();
 
68
                release_(dir);
 
69
 
 
70
        }
 
71
        cont_(a);
 
72
        return NULL; 
 
73
}
 
74
 
61
75
CSFile *CSPath::createFile(int mode)
62
76
{
63
 
        CSFile  *file;
64
 
        CSPath  *dir;
 
77
        CSFile  *file = NULL;
65
78
        bool    retry = false;
66
79
 
67
 
        CLOBBER_PROTECT(retry);
68
 
 
69
80
        enter_();
70
 
        /* Create and open the file: */
71
 
        do {
72
 
                try_(a) {
73
 
                        file = openFile(mode | CSFile::CREATE);
74
 
                        retry = false;
75
 
                }
76
 
                catch_(a) {
77
 
                        if (retry || !CSFile::isDirNotFound(&self->myException))
78
 
                                throw_();
79
 
 
80
 
                        /* Make sure the parent directory exists: */
81
 
                        dir = CSPath::newPath(RETAIN(this), "..");
82
 
                        try_(b) {
83
 
                                dir->makePath();
84
 
                        }
85
 
                        finally_(b) {
86
 
                                dir->release();
87
 
                        }
88
 
                        finally_end_block(b);
89
 
 
90
 
                        retry = true;
91
 
                }
92
 
                cont_(a);
 
81
        while (file == NULL) {
 
82
                file = try_CreateAndOpen(self, mode, retry);
 
83
                retry = true;
93
84
        }
94
 
        while (retry);
95
85
        return_(file);
96
86
}
97
87
 
157
147
        }
158
148
 
159
149
        path = CSPath::newPath(RETAIN(this), "..");
160
 
        try_(a) {
161
 
                path->makePath();
162
 
                makeDir();
163
 
        }
164
 
        finally_(a) {
165
 
                path->release();
166
 
        }
167
 
        finally_end_block(a);
 
150
        push_(path);
 
151
        
 
152
        path->makePath();
 
153
        makeDir();
 
154
        
 
155
        release_(path);
 
156
 
168
157
        exit_();
169
158
}
170
159
 
227
216
 
228
217
bool CSPath::isLink()
229
218
{
230
 
        struct stat sb;
 
219
        bool link;
231
220
        enter_();
232
221
 
233
 
        if (lstat(iPath->getCString(), &sb) == -1)
234
 
                CSException::throwFileError(CS_CONTEXT, iPath, errno);
235
 
                
236
 
        return_(S_ISLNK(sb.st_mode));
 
222
        link = sys_isLink(iPath->getCString());
 
223
        
 
224
        return_(link);
237
225
}
238
226
 
239
227
bool CSPath::isEmpty()
249
237
                return_(false);
250
238
 
251
239
        dir = openDirectory();
252
 
        try_(a) {
253
 
                if (dir->next())
254
 
                        result = false;
255
 
        }
256
 
        finally_(a) {
257
 
                dir->release(); 
258
 
        }
259
 
        finally_end_block(a);
 
240
        push_(dir);
 
241
        
 
242
        if (dir->next())
 
243
                result = false;
 
244
 
 
245
        release_(dir);
260
246
        return_(result);
261
247
}
262
248
 
274
260
                CSException::throwFileError(CS_CONTEXT, iPath, ENOTDIR);
275
261
 
276
262
        dir = openDirectory();
277
 
        try_(a) {
278
 
                while (dir->next()) {
279
 
                        path = CSPath::newPath(RETAIN(this), dir->name());
280
 
                        if (dir->isFile())
281
 
                                path->remove();
282
 
                        else
283
 
                                path->removeDir();
284
 
                        path->release();
285
 
                        path = NULL;
286
 
                }
287
 
        }
288
 
        finally_(a) {
289
 
                if (path)
290
 
                        path->release();
291
 
                dir->release(); 
292
 
        }
293
 
        finally_end_block(a);
 
263
        push_(dir);
 
264
 
 
265
        while (dir->next()) {
 
266
                path = CSPath::newPath(RETAIN(this), dir->name());
 
267
                push_(path);
 
268
                if (dir->isFile())
 
269
                        path->remove();
 
270
                else
 
271
                        path->removeDir();
 
272
                release_(path);
 
273
        }
 
274
 
 
275
        release_(dir);
 
276
        exit_();
 
277
}
 
278
 
 
279
void CSPath::emptyPath()
 
280
{
 
281
        CSDirectory *dir;
 
282
        CSPath          *path = NULL;
 
283
        bool            is_dir;
 
284
 
 
285
        enter_();
 
286
        if (!exists(&is_dir))
 
287
                exit_();
 
288
 
 
289
        if (!is_dir)
 
290
                CSException::throwFileError(CS_CONTEXT, iPath, ENOTDIR);
 
291
 
 
292
        dir = openDirectory();
 
293
        push_(dir);
 
294
 
 
295
        while (dir->next()) {
 
296
                path = CSPath::newPath(RETAIN(this), dir->name());
 
297
                push_(path);
 
298
                if (dir->isFile())
 
299
                        path->remove();
 
300
                else
 
301
                        path->emptyPath();
 
302
                release_(path);
 
303
        }
 
304
 
 
305
        release_(dir);
294
306
        exit_();
295
307
}
296
308
 
317
329
 
318
330
void CSPath::moveTo(CSPath *in_to_path)
319
331
{
320
 
        CSPath  *to_path = in_to_path;
 
332
        CSPath  *to_path = NULL;
321
333
        bool    is_dir;
322
334
 
323
335
        enter_();
 
336
        push_(in_to_path);
 
337
        
324
338
        if (!exists(NULL))
325
339
                CSException::throwFileError(CS_CONTEXT, iPath, ENOENT);
326
340
 
327
 
        try_(a) {
328
 
                if (to_path->exists(&is_dir)) {
329
 
                        if (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);
333
 
                        }
334
 
                        else
335
 
                                CSException::throwFileError(CS_CONTEXT, to_path->getCString(), ENOTDIR);
 
341
        if (in_to_path->exists(&is_dir)) {
 
342
                if (is_dir) {
 
343
                        to_path = CSPath::newPath(RETAIN(in_to_path), getNameCString());
 
344
                        push_(to_path);
 
345
                        if (to_path->exists(NULL))
 
346
                                CSException::throwFileError(CS_CONTEXT, to_path->getCString(), EEXIST);
 
347
                        pop_(to_path);
336
348
                }
337
 
                move(to_path);
338
 
        }
339
 
        finally_(a) {
340
 
                if (to_path != in_to_path)
341
 
                        to_path->release();
342
 
        }
343
 
        finally_end_block(a);
 
349
                else
 
350
                        CSException::throwFileError(CS_CONTEXT, to_path->getCString(), ENOTDIR);
 
351
        } else
 
352
                to_path = RETAIN(in_to_path);
 
353
                
 
354
        move(to_path);
344
355
 
 
356
        release_(in_to_path);
345
357
        exit_();
346
358
}
347
359
 
390
402
        return cs_last_name_of_path(str);
391
403
}
392
404
 
 
405
off64_t CSPath::getSize(const char *path)
 
406
{
 
407
        off64_t size;
 
408
 
 
409
        info(path, NULL, &size, NULL);
 
410
        return size;
 
411
}
 
412
 
393
413
off64_t CSPath::getSize()
394
414
{
395
415
        off64_t size;
406
426
        return is_dir;
407
427
}
408
428
 
409
 
/*
410
 
 * ---------------------------------------------------------------
411
 
 * A UNIX PATH
412
 
 */
413
 
 
414
429
bool CSPath::exists(bool *is_dir)
415
430
{
416
 
        int err;
417
 
 
418
 
        err = access(iPath->getCString(), F_OK);
419
 
        if (err == -1)
 
431
        if (!sys_exists(iPath->getCString()))
420
432
                return false;
 
433
                
421
434
        if (is_dir)
422
435
                *is_dir = isDir();
423
436
        return true;
424
437
}
425
438
 
 
439
void CSPath::info(const char *path, bool *is_dir, off64_t *size, CSTime *mod_time)
 
440
{
 
441
        sys_stat(path, is_dir, size, mod_time);
 
442
        
 
443
}
 
444
 
426
445
void CSPath::info(bool *is_dir, off64_t *size, CSTime *mod_time)
427
446
{
428
 
        struct stat sb;
429
 
 
430
 
        if (stat(iPath->getCString(), &sb) == -1)
431
 
                CSException::throwFileError(CS_CONTEXT, iPath, errno);
432
 
        if (is_dir)
433
 
                *is_dir = sb.st_mode & S_IFDIR;
434
 
        if (size)
435
 
                *size = sb.st_size;
436
 
        if (mod_time)
437
 
#ifdef __USE_MISC
438
 
                /* This is the Linux version: */
439
 
                mod_time->setUTC1970(sb.st_mtim.tv_sec, sb.st_mtim.tv_nsec);
440
 
#else
441
 
                mod_time->setUTC1970(sb.st_mtime, 0);
442
 
#endif
 
447
        info(iPath->getCString(), is_dir, size, mod_time);
443
448
}
444
449
 
445
450
CSFile *CSPath::openFile(int mode)
456
461
 
457
462
void CSPath::removeFile()
458
463
{
459
 
        if (unlink(iPath->getCString()) == -1) {
460
 
                int err = errno;
461
 
 
462
 
                if (err != ENOENT)
463
 
                        CSException::throwFileError(CS_CONTEXT, iPath, err);
464
 
        }
465
 
}
466
 
 
467
 
static void cs_set_stats(char *path)
468
 
{
469
 
        char            super_path[PATH_MAX];
470
 
        struct stat     stats;
471
 
        char            *ptr;
472
 
 
473
 
        ptr = cs_last_name_of_path(path);
474
 
        if (ptr == path) 
475
 
                strcpy(super_path, ".");
476
 
        else {
477
 
                cs_strcpy(PATH_MAX, super_path, path);
478
 
 
479
 
                if ((ptr = cs_last_name_of_path(super_path)))
480
 
                        *ptr = 0;
481
 
        }
482
 
        if (stat(super_path, &stats) == -1)
483
 
                CSException::throwFileError(CS_CONTEXT, path, errno);
484
 
 
485
 
        if (chmod(path, stats.st_mode) == -1)
486
 
                CSException::throwFileError(CS_CONTEXT, path, errno);
487
 
 
488
 
        /*chown(path, stats.st_uid, stats.st_gid);*/
 
464
        sys_removeFile(iPath->getCString());
489
465
}
490
466
 
491
467
void CSPath::makeDir()
495
471
        cs_strcpy(PATH_MAX, path, iPath->getCString());
496
472
        cs_remove_dir_char(path);
497
473
 
498
 
        if (mkdir(path, S_IRWXU | S_IRWXG | S_IRWXO) == -1)
499
 
                CSException::throwFileError(CS_CONTEXT, iPath, errno);
500
 
 
501
 
        cs_set_stats(path);
 
474
        sys_makeDir(path);
502
475
}
503
476
 
504
477
CSDirectory *CSPath::openDirectory()
516
489
void CSPath::removeDir()
517
490
{                       
518
491
        emptyDir();
519
 
        if (rmdir(iPath->getCString()) == -1) {
520
 
                int err = errno;
521
 
 
522
 
                if (err != ENOENT)
523
 
                        CSException::throwFileError(CS_CONTEXT, iPath, err);
524
 
        }
 
492
        sys_removeDir(iPath->getCString());
525
493
}
526
494
 
527
495
void CSPath::rename(const char *name)
536
504
        cs_add_dir_char(PATH_MAX, new_path);
537
505
        cs_strcat(PATH_MAX, new_path, name);
538
506
        
 
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);
 
510
        
539
511
        tmp_path = CSString::newString(new_path);
540
512
        push_(tmp_path);
541
513
        
542
 
        if (unix_file_rename(iPath->getCString(), new_path) == -1)
543
 
                CSException::throwFileError(CS_CONTEXT, iPath, errno);
 
514
        sys_rename(iPath->getCString(), new_path);
544
515
                
545
516
        pop_(tmp_path);
 
517
        unlock_(&iRename_lock);
 
518
        
546
519
        old_path = iPath;
547
520
        iPath = tmp_path;
548
521
        
552
525
 
553
526
void CSPath::move(CSPath *to_path)
554
527
{
 
528
        enter_();
 
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);
 
532
                
555
533
        /* 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);
 
534
        sys_rename(iPath->getCString(), to_path->getCString());
 
535
        unlock_(&iRename_lock);
 
536
        exit_();
558
537
}
559
538
 
560
539
CSPath *CSPath::getCWD()
561
540
{
562
 
        char path[MAXPATHLEN];
563
 
 
564
 
        if (!getcwd(path, MAXPATHLEN))
565
 
                CSException::throwOSError(CS_CONTEXT, errno);
566
 
 
 
541
        char path[PATH_MAX];
 
542
 
 
543
        sys_getcwd(path, PATH_MAX);
567
544
        return newPath(path);
568
545
}
569
546