~drizzle-trunk/drizzle/development

1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
1
/* Copyright (c) 2008 PrimeBase Technologies GmbH, Germany
2
 *
3
 * PrimeBase Media Stream for MySQL
4
 *
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.
9
 *
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.
14
 *
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
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
17
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
18
 *
19
 * Original author: Paul McCullagh
20
 * Continued development: Barry Leslie
21
 *
22
 * 2007-06-07
23
 *
24
 * CORE SYSTEM:
25
 * Basic file system path.
26
 *
27
 */
28
29
#include "CSConfig.h"
30
31
#include <string.h>
32
#include <stdio.h>
33
34
#include "CSStrUtil.h"
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
35
#include "CSSys.h"
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
36
#include "CSFile.h"
37
#include "CSDirectory.h"
38
#include "CSPath.h"
39
#include "CSGlobal.h"
40
41
/*
42
 * ---------------------------------------------------------------
43
 * CORE SYSTEM PATH
44
 */
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
45
CSLock	CSPath::iRename_lock;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
46
47
CSPath *CSPath::iCWD = NULL;
48
49
CSPath::~CSPath()
50
{
51
	if (iPath)
52
		iPath->release();
53
}
54
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
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
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
75
CSFile *CSPath::createFile(int mode)
76
{
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
77
	CSFile	*file = NULL;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
78
	bool	retry = false;
79
80
	enter_();
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
81
	while (file == NULL) {
82
		file = try_CreateAndOpen(self, mode, retry);
83
		retry = true;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
84
	}
85
	return_(file);
86
}
87
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.
92
 */
93
void CSPath::copyFile(CSPath *in_to_file, bool overwrite)
94
{
95
	CSPath			*to_file = in_to_file;
96
	bool			is_dir;
97
	CSFile			*infile, *outfile;
98
99
	enter_();
100
	push_(in_to_file);
101
	
102
	if (to_file->exists(&is_dir)) {
103
		if (is_dir) {
104
			to_file = CSPath::newPath(RETAIN(in_to_file), getNameCString());
105
			push_(to_file);
106
			
107
			if (to_file->exists(&is_dir)) {	
108
				if (!overwrite)
109
					CSException::throwFileError(CS_CONTEXT, to_file->getCString(), EEXIST);
110
				to_file->remove();
111
			}
112
		}
113
		else if (!overwrite)
114
			CSException::throwFileError(CS_CONTEXT, to_file->getCString(), EEXIST);
115
	}
116
117
	infile = openFile(CSFile::READONLY);
118
	push_(infile);
119
120
	outfile = to_file->createFile(CSFile::TRUNCATE);
121
	push_(outfile);
122
	
123
	CSStream::pipe(outfile->getOutputStream(), infile->getInputStream());
124
	release_(outfile);
125
	release_(infile);
126
	
127
	if (to_file != in_to_file)
128
		release_(to_file);
129
		
130
	release_(in_to_file);
131
	exit_();
132
}
133
134
void CSPath::makePath()
135
{
136
	CSPath	*path;
137
	bool	is_dir;
138
139
	enter_();
140
	if (iPath->length() <= 1)
141
		exit_();
142
143
	if (exists(&is_dir)) {
144
		if (!is_dir)
145
			CSException::throwFileError(CS_CONTEXT, iPath, EEXIST);
146
		exit_();
147
	}
148
149
	path = CSPath::newPath(RETAIN(this), "..");
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
150
	push_(path);
151
	
152
	path->makePath();
153
	makeDir();
154
	
155
	release_(path);
156
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
157
	exit_();
158
}
159
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.
164
 */
165
void CSPath::copyDir(CSPath *in_to_dir, bool overwrite)
166
{
167
	CSPath		*to_dir = in_to_dir;
168
	bool		is_dir;
169
	CSDirectory *dir = NULL;
170
	CSPath		*path = NULL;
171
172
	enter_();
173
	push_(in_to_dir);
174
	
175
	if (to_dir->exists(&is_dir)) {
176
		if (!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());
180
		push_(to_dir);
181
		
182
		if (to_dir->exists(&is_dir)) {
183
			if (!overwrite)
184
				CSException::throwFileError(CS_CONTEXT, to_dir->getCString(), EEXIST);
185
			to_dir->remove();
186
		}
187
	}
188
 
189
	/* Make the directory and copy the contents of the source
190
	 * into it:
191
	 */
192
	to_dir->makePath();
193
194
	dir = openDirectory();
195
	push_(dir);
196
	while (dir->next()) {
197
		self->interrupted();
198
		path = CSPath::newPath(RETAIN(this), dir->name());
199
		push_(path);
200
		if (dir->isFile())
201
			path->copyFile(RETAIN(to_dir), overwrite);
202
		else
203
			path->copyDir(RETAIN(to_dir), overwrite);
204
		release_(path);
205
	}
206
	release_(dir);
207
	
208
	if (to_dir != in_to_dir)
209
		release_(to_dir);
210
		
211
	release_(in_to_dir);
212
	
213
	exit_();
214
}
215
216
217
bool CSPath::isLink()
218
{
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
219
	bool link;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
220
	enter_();
221
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
222
	link = sys_isLink(iPath->getCString());
223
	
224
	return_(link);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
225
}
226
227
bool CSPath::isEmpty()
228
{
229
	CSDirectory *dir = NULL;
230
	bool		is_dir, result = true;
231
232
	enter_();
233
	if (!exists(&is_dir))
234
		return_(true);
235
236
	if (!is_dir)
237
		return_(false);
238
239
	dir = openDirectory();
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
240
	push_(dir);
241
	
242
	if (dir->next())
243
		result = false;
244
245
	release_(dir);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
246
	return_(result);
247
}
248
249
void CSPath::emptyDir()
250
{
251
	CSDirectory *dir;
252
	CSPath		*path = NULL;
253
	bool		is_dir;
254
255
	enter_();
256
	if (!exists(&is_dir))
257
		exit_();
258
259
	if (!is_dir)
260
		CSException::throwFileError(CS_CONTEXT, iPath, ENOTDIR);
261
262
	dir = openDirectory();
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
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);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
306
	exit_();
307
}
308
309
void CSPath::copyTo(CSPath *to_path, bool overwrite)
310
{
311
	bool is_dir;
312
313
	enter_();
314
	push_(to_path);
315
	if (!exists(&is_dir))
316
		CSException::throwFileError(CS_CONTEXT, iPath, ENOENT);
317
318
	pop_(to_path);
319
	if (is_dir)
320
		/* The source is a directory. */
321
		copyDir(to_path, overwrite);
322
	else {
323
		/* The source is not a directory: */
324
		copyFile(to_path, overwrite);
325
	}
326
327
	exit_();
328
}
329
330
void CSPath::moveTo(CSPath *in_to_path)
331
{
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
332
	CSPath	*to_path = NULL;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
333
	bool	is_dir;
334
335
	enter_();
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
336
	push_(in_to_path);
337
	
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
338
	if (!exists(NULL))
339
		CSException::throwFileError(CS_CONTEXT, iPath, ENOENT);
340
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
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);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
348
		}
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
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);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
355
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
356
	release_(in_to_path);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
357
	exit_();
358
}
359
360
void CSPath::remove()
361
{
362
	bool is_dir;
363
364
	if (exists(&is_dir)) {
365
		if (is_dir) {
366
			emptyDir();
367
			removeDir();
368
		}
369
		else
370
			removeFile();
371
	}
372
}
373
374
375
void CSPath::touch(bool create_path)
376
{
377
	CSFile *file;
378
379
	enter_();
380
	if (create_path)
381
		file = createFile(CSFile::READONLY);
382
	else
383
		file = openFile(CSFile::READONLY | CSFile::CREATE);
384
	file->release();
385
	exit_();
386
}
387
388
CSString *CSPath::getString()
389
{ 
390
	return iPath;
391
}
392
393
const char *CSPath::getCString()
394
{
395
	return iPath->getCString();
396
}
397
398
const char *CSPath::getNameCString()
399
{
400
	const char *str = getCString();
401
	
402
	return cs_last_name_of_path(str);
403
}
404
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
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
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
413
off64_t CSPath::getSize()
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
414
{
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
415
	off64_t size;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
416
417
	info((bool *) NULL, &size, (CSTime *) NULL);
418
	return size;
419
}
420
421
bool CSPath::isDir()
422
{
423
	bool	is_dir;
424
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
425
	info(&is_dir, (off64_t *) NULL, (CSTime *) NULL);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
426
	return is_dir;
427
}
428
429
bool CSPath::exists(bool *is_dir)
430
{
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
431
	if (!sys_exists(iPath->getCString()))
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
432
		return false;
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
433
		
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
434
	if (is_dir)
435
		*is_dir = isDir();
436
	return true;
437
}
438
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
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
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
445
void CSPath::info(bool *is_dir, off64_t *size, CSTime *mod_time)
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
446
{
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
447
	info(iPath->getCString(), is_dir, size, mod_time);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
448
}
449
450
CSFile *CSPath::openFile(int mode)
451
{
452
	CSFile *file;
453
454
	enter_();
455
	file = CSFile::newFile(RETAIN(this));
456
	push_(file);
457
	file->open(mode);
458
	pop_(file);
459
	return_(file);
460
}
461
462
void CSPath::removeFile()
463
{
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
464
	sys_removeFile(iPath->getCString());
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
465
}
466
467
void CSPath::makeDir()
468
{
469
	char path[PATH_MAX];
470
471
	cs_strcpy(PATH_MAX, path, iPath->getCString());
472
	cs_remove_dir_char(path);
473
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
474
	sys_makeDir(path);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
475
}
476
477
CSDirectory *CSPath::openDirectory()
478
{
479
	CSDirectory *dir;
480
481
	enter_();
482
	dir = CSDirectory::newDirectory(RETAIN(this));
483
	push_(dir);
484
	dir->open();
485
	pop_(dir);
486
	return_(dir);
487
}
488
489
void CSPath::removeDir()
490
{			
491
	emptyDir();
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
492
	sys_removeDir(iPath->getCString());
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
493
}
494
495
void CSPath::rename(const char *name)
496
{
497
	char new_path[PATH_MAX];
498
	CSString *tmp_path, *old_path = iPath;
499
	
500
	enter_();
501
	
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);
506
	
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
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
	
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
511
	tmp_path = CSString::newString(new_path);
512
	push_(tmp_path);
513
	
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
514
	sys_rename(iPath->getCString(), new_path);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
515
		
516
	pop_(tmp_path);
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
517
	unlock_(&iRename_lock);
518
	
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
519
	old_path = iPath;
520
	iPath = tmp_path;
521
	
522
	old_path->release();
523
	exit_();
524
}
525
526
void CSPath::move(CSPath *to_path)
527
{
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
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
		
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
533
	/* Cannot move from TD to non-TD: */
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
534
	sys_rename(iPath->getCString(), to_path->getCString());
535
	unlock_(&iRename_lock);
536
	exit_();
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
537
}
538
539
CSPath *CSPath::getCWD()
540
{
1841.1.3 by Barry.Leslie at PrimeBase
Merged changes from lp:pbms. These changes should remove any danger
541
	char path[PATH_MAX];
542
543
	sys_getcwd(path, PATH_MAX);
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
544
	return newPath(path);
545
}
546
547
CSPath *CSPath::newPath(const char *path)
548
{
549
	if (!path)
550
		CSException::throwAssertion(CS_CONTEXT, "Initial string may not be NULL");
551
	return newPath(CSString::newString(path));
552
}
553
554
CSPath *CSPath::newPath(CSString *path)
555
{
556
	CSPath *p;
557
558
	enter_();
559
	push_(path);
560
	new_(p, CSPath());
561
562
	/* Adjust the path string so that it does not have
563
	 * a terminating CS_DIR_CHAR:
564
	 */
565
	if (path->endsWith(CS_DIR_DELIM) && path->length() > 1) {
566
		p->iPath = path->left(CS_DIR_DELIM, -1);
567
		path->release();
568
	}
569
	else
570
		p->iPath = path;
571
	pop_(path);
572
	return_(p);
573
}
574
575
CSPath *CSPath::newPath(CSPath *cwd, const char *path)
576
{
577
	char abs_path[PATH_MAX];
578
579
	enter_();
580
	cs_make_absolute_path(PATH_MAX, abs_path, path, cwd->getCString());
581
	cwd->release();
582
	CSPath *p = newPath(abs_path);
583
	return_(p);
584
}
585
586
CSPath *CSPath::newPath(CSString *cwd, const char *path)
587
{
588
	char abs_path[PATH_MAX];
589
590
	enter_();
591
	cs_make_absolute_path(PATH_MAX, abs_path, path, cwd->getCString());
592
	cwd->release();
593
	CSPath *p = newPath(abs_path);
594
	return_(p);
595
}
596
597
CSPath *CSPath::newPath(const char *cwd, CSString *path)
598
{
599
	char abs_path[PATH_MAX];
600
601
	enter_();
602
	cs_make_absolute_path(PATH_MAX, abs_path, path->getCString(), cwd);
603
	path->release();
604
	CSPath *p = newPath(abs_path);
605
	return_(p);
606
}
607
608
CSPath *CSPath::newPath(const char *cwd, const char *path)
609
{
610
	char abs_path[PATH_MAX];
611
612
	enter_();
613
	cs_make_absolute_path(PATH_MAX, abs_path, path, cwd);
614
	CSPath *p = newPath(abs_path);
615
	return_(p);
616
}
617