2
Copyright (C) 2008- The University of Notre Dame
3
This software is distributed under the GNU General Public License.
4
See the file COPYING for details.
7
#include "chirp_filesystem.h"
8
#include "chirp_local.h"
9
#include "chirp_protocol.h"
11
#include "create_dir.h"
12
#include "hash_table.h"
14
#include "int_sizes.h"
15
#include "stringtools.h"
17
#include "delete_dir.h"
28
#ifdef HAS_SYS_STATFS_H
29
#include <sys/statfs.h>
31
#ifdef HAS_SYS_STATVFS_H
32
#include <sys/statvfs.h>
34
#include <sys/param.h>
35
#include <sys/mount.h>
37
/* Cygwin does not have 64-bit I/O, while Darwin has it by default. */
39
#if CCTOOLS_OPSYS_CYGWIN || CCTOOLS_OPSYS_DARWIN || CCTOOLS_OPSYS_FREEBSD
46
#define fseeko64 fseeko
47
#define ftruncate64 ftruncate
48
#define truncate64 truncate
49
#define statfs64 statfs
50
#define fstatfs64 fstatfs
53
#if CCTOOLS_OPSYS_DARWIN
57
/* Solaris has statfs, but it doesn't work! Use statvfs instead. */
59
#if CCTOOLS_OPSYS_SUNOS
60
#define statfs statvfs
61
#define fstatfs fstatvfs
62
#define statfs64 statvfs64
63
#define fstatfs64 fstatvfs64
67
#define COPY_CSTAT( a, b )\
68
memset(&(b),0,sizeof(b));\
69
(b).cst_dev = (a).st_dev;\
70
(b).cst_ino = (a).st_ino;\
71
(b).cst_mode = (a).st_mode;\
72
(b).cst_nlink = (a).st_nlink;\
73
(b).cst_uid = (a).st_uid;\
74
(b).cst_gid = (a).st_gid;\
75
(b).cst_rdev = (a).st_rdev;\
76
(b).cst_size = (a).st_size;\
77
(b).cst_blksize = (a).st_blksize;\
78
(b).cst_blocks = (a).st_blocks;\
79
(b).cst_atime = (a).st_atime;\
80
(b).cst_mtime = (a).st_mtime;\
81
(b).cst_ctime = (a).st_ctime;
84
INT64_T chirp_local_file_size( const char *path )
86
struct chirp_stat info;
87
if(chirp_local_stat(path,&info)==0) {
94
INT64_T chirp_local_fd_size( int fd )
96
struct chirp_stat info;
97
if(chirp_local_fstat(fd,&info)==0) {
104
INT64_T chirp_local_open( const char *path, INT64_T flags, INT64_T mode )
106
mode = 0600 | (mode&0100);
107
return open64(path,flags,(int)mode);
110
INT64_T chirp_local_close( int fd )
115
INT64_T chirp_local_pread( int fd, void *buffer, INT64_T length, INT64_T offset )
118
result = full_pread64(fd,buffer,length,offset);
119
if(result<0 && errno==ESPIPE) {
120
/* if this is a pipe, return whatever amount is available */
121
result = read(fd,buffer,length);
126
INT64_T chirp_local_sread( int fd, void *vbuffer, INT64_T length, INT64_T stride_length, INT64_T stride_skip, INT64_T offset )
130
char *buffer = vbuffer;
132
if(stride_length<0 || stride_skip<0 || offset<0) {
137
while(length>=stride_length) {
138
actual = chirp_local_pread(fd,&buffer[total],stride_length,offset);
142
offset += stride_skip;
143
if(actual==stride_length) {
164
INT64_T chirp_local_pwrite( int fd, const void *buffer, INT64_T length, INT64_T offset )
167
result = full_pwrite64(fd,buffer,length,offset);
168
if(result<0 && errno==ESPIPE) {
169
/* if this is a pipe, then just write without the offset. */
170
result = full_write(fd,buffer,length);
175
INT64_T chirp_local_swrite( int fd, const void *vbuffer, INT64_T length, INT64_T stride_length, INT64_T stride_skip, INT64_T offset )
179
const char *buffer = vbuffer;
181
if(stride_length<0 || stride_skip<0 || offset<0) {
186
while(length>=stride_length) {
187
actual = chirp_local_pwrite(fd,&buffer[total],stride_length,offset);
191
offset += stride_skip;
192
if(actual==stride_length) {
213
INT64_T chirp_local_fstat( int fd, struct chirp_stat *buf )
217
result = fstat64(fd,&info);
218
if(result==0) COPY_CSTAT(info,*buf);
219
buf->cst_mode = buf->cst_mode & (~0077);
223
INT64_T chirp_local_fstatfs( int fd, struct chirp_statfs *buf )
225
struct statfs64 info;
227
result = fstatfs64(fd,&info);
229
memset(buf,0,sizeof(*buf));
230
#ifdef CCTOOLS_OPSYS_SUNOS
231
buf->f_type = info.f_fsid;
232
buf->f_bsize = info.f_frsize;
234
buf->f_type = info.f_type;
235
buf->f_bsize = info.f_bsize;
237
buf->f_blocks = info.f_blocks;
238
buf->f_bavail = info.f_bavail;
239
buf->f_bfree = info.f_bfree;
240
buf->f_files = info.f_files;
241
buf->f_ffree = info.f_ffree;
246
INT64_T chirp_local_fchown( int fd, INT64_T uid, INT64_T gid )
248
// Changing file ownership is silently ignored,
249
// because permissions are handled through the ACL model.
253
INT64_T chirp_local_fchmod( int fd, INT64_T mode )
255
// A remote user can change some of the permissions bits,
256
// which only affect local users, but we don't let them
257
// take away the owner bits, which would affect the Chirp server.
258
mode = 0600 | (mode&0177);
259
return fchmod(fd,mode);
262
INT64_T chirp_local_ftruncate( int fd, INT64_T length )
264
return ftruncate64(fd,length);
267
INT64_T chirp_local_fsync( int fd )
272
void * chirp_local_opendir( const char *path )
274
return opendir(path);
277
char * chirp_local_readdir( void *dir )
288
void chirp_local_closedir( void *dir )
293
INT64_T chirp_local_getfile( const char *path, struct link *link, time_t stoptime )
297
struct chirp_stat info;
299
result = chirp_local_stat(path,&info);
300
if(result<0) return result;
302
if(S_ISDIR(info.cst_mode)) {
307
if(S_ISFIFO(info.cst_mode)) {
312
fd = chirp_local_open(path,O_RDONLY,0);
314
INT64_T length = info.cst_size;
315
link_putfstring(link,"%lld\n",stoptime,length);
316
result = link_stream_from_fd(link,fd,length,stoptime);
317
chirp_local_close(fd);
325
INT64_T chirp_local_putfile( const char *path, struct link *link, INT64_T length, INT64_T mode, time_t stoptime )
330
mode = 0600 | (mode&0100);
332
fd = chirp_local_open(path,O_WRONLY|O_CREAT|O_TRUNC,(int)mode);
334
link_putliteral(link,"0\n",stoptime);
335
result = link_stream_to_fd(link,fd,length,stoptime);
337
if(result>=0) link_soak(link,length-result,stoptime);
340
chirp_local_close(fd);
347
INT64_T chirp_local_mkfifo( const char *path )
349
return mknod(path,0700|S_IFIFO,0);
352
INT64_T chirp_local_unlink( const char *path )
354
int result = unlink(path);
357
On Solaris, an unlink on a directory
358
returns EPERM when it should return EISDIR.
359
Check for this cast, and then fix it.
362
if(result<0 && errno==EPERM) {
364
result = stat64(path,&info);
365
if(result==0 && S_ISDIR(info.st_mode)) {
377
INT64_T chirp_local_rename( const char *path, const char *newpath )
379
return rename(path,newpath);
382
INT64_T chirp_local_link( const char *path, const char *newpath )
384
return link(path,newpath);
387
INT64_T chirp_local_symlink( const char *path, const char *newpath )
389
return symlink(path,newpath);
392
INT64_T chirp_local_readlink( const char *path, char *buf, INT64_T length )
394
return readlink(path,buf,length);
397
INT64_T chirp_local_chdir( const char *path)
402
INT64_T chirp_local_mkdir( const char *path, INT64_T mode )
404
return mkdir(path,0700);
408
rmdir is a little unusual.
409
An 'empty' directory may contain some administrative
410
files such as an ACL and an allocation state.
411
Only delete the directory if it contains only those files.
414
INT64_T chirp_local_rmdir( const char *path )
420
dir = chirp_local_opendir(path);
422
while((d=chirp_local_readdir(dir))) {
423
if(!strcmp(d,".")) continue;
424
if(!strcmp(d,"..")) continue;
425
if(!strncmp(d,".__",3)) continue;
429
chirp_local_closedir(dir);
432
if(delete_dir(path)) {
446
INT64_T chirp_local_stat( const char *path, struct chirp_stat *buf )
450
result = stat64(path,&info);
451
if(result==0) COPY_CSTAT(info,*buf);
455
INT64_T chirp_local_lstat( const char *path, struct chirp_stat *buf )
459
result = lstat64(path,&info);
460
if(result==0) COPY_CSTAT(info,*buf);
464
INT64_T chirp_local_statfs( const char *path, struct chirp_statfs *buf )
466
struct statfs64 info;
468
result = statfs64(path,&info);
470
memset(buf,0,sizeof(*buf));
471
#ifdef CCTOOLS_OPSYS_SUNOS
472
buf->f_type = info.f_fsid;
473
buf->f_bsize = info.f_frsize;
475
buf->f_type = info.f_type;
476
buf->f_bsize = info.f_bsize;
478
buf->f_blocks = info.f_blocks;
479
buf->f_bavail = info.f_bavail;
480
buf->f_bfree = info.f_bfree;
481
buf->f_files = info.f_files;
482
buf->f_ffree = info.f_ffree;
487
INT64_T chirp_local_access( const char *path, INT64_T mode )
489
return access(path,mode);
492
INT64_T chirp_local_chmod( const char *path, INT64_T mode )
494
struct chirp_stat info;
496
int result = chirp_local_stat(path,&info);
497
if(result<0) return result;
499
// A remote user can change some of the permissions bits,
500
// which only affect local users, but we don't let them
501
// take away the owner bits, which would affect the Chirp server.
503
if(S_ISDIR(info.cst_mode)) {
504
// On a directory, the user cannot set the execute bit.
505
mode = 0700 | (mode&0077);
507
// On a file, the user can set the execute bit.
508
mode = 0600 | (mode&0177);
511
return chmod(path,mode);
514
INT64_T chirp_local_chown( const char *path, INT64_T uid, INT64_T gid )
516
// Changing file ownership is silently ignored,
517
// because permissions are handled through the ACL model.
521
INT64_T chirp_local_lchown( const char *path, INT64_T uid, INT64_T gid )
523
// Changing file ownership is silently ignored,
524
// because permissions are handled through the ACL model.
528
INT64_T chirp_local_truncate( const char *path, INT64_T length )
530
return truncate64(path,length);
533
INT64_T chirp_local_utime( const char *path, time_t actime, time_t modtime )
537
ut.modtime = modtime;
538
return utime(path,&ut);
541
INT64_T chirp_local_md5( const char *path, unsigned char digest[16] )
543
return md5_file(path,digest);
546
INT64_T chirp_local_init (const char *path)
551
INT64_T chirp_local_destroy (void)
556
struct chirp_filesystem chirp_local_fs = {
570
chirp_local_ftruncate,
575
chirp_local_closedir,
585
chirp_local_readlink,
596
chirp_local_truncate,
600
chirp_local_file_size,