~ubuntu-branches/ubuntu/vivid/cctools/vivid

« back to all changes in this revision

Viewing changes to chirp/src/chirp_local.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Hanke
  • Date: 2011-05-07 09:05:00 UTC
  • Revision ID: james.westby@ubuntu.com-20110507090500-lqpmdtwndor6e7os
Tags: upstream-3.3.2
ImportĀ upstreamĀ versionĀ 3.3.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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.
 
5
*/
 
6
 
 
7
#include "chirp_filesystem.h"
 
8
#include "chirp_local.h"
 
9
#include "chirp_protocol.h"
 
10
 
 
11
#include "create_dir.h"
 
12
#include "hash_table.h"
 
13
#include "xmalloc.h"
 
14
#include "int_sizes.h"
 
15
#include "stringtools.h"
 
16
#include "full_io.h"
 
17
#include "delete_dir.h"
 
18
#include "md5.h"
 
19
 
 
20
#include <stdlib.h>
 
21
#include <stdio.h>
 
22
#include <errno.h>
 
23
#include <string.h>
 
24
#include <dirent.h>
 
25
#include <utime.h>
 
26
#include <sys/file.h>
 
27
#include <sys/stat.h>
 
28
#ifdef HAS_SYS_STATFS_H
 
29
#include <sys/statfs.h>
 
30
#endif
 
31
#ifdef HAS_SYS_STATVFS_H
 
32
#include <sys/statvfs.h>
 
33
#endif
 
34
#include <sys/param.h>
 
35
#include <sys/mount.h>
 
36
 
 
37
/* Cygwin does not have 64-bit I/O, while Darwin has it by default. */
 
38
 
 
39
#if CCTOOLS_OPSYS_CYGWIN || CCTOOLS_OPSYS_DARWIN || CCTOOLS_OPSYS_FREEBSD
 
40
#define fopen64 fopen
 
41
#define open64 open
 
42
#define lseek64 lseek
 
43
#define stat64 stat
 
44
#define fstat64 fstat
 
45
#define lstat64 lstat
 
46
#define fseeko64 fseeko
 
47
#define ftruncate64 ftruncate
 
48
#define truncate64 truncate
 
49
#define statfs64 statfs
 
50
#define fstatfs64 fstatfs
 
51
#endif
 
52
 
 
53
#if CCTOOLS_OPSYS_DARWIN
 
54
#define lchown chown
 
55
#endif
 
56
 
 
57
/* Solaris has statfs, but it doesn't work! Use statvfs instead. */
 
58
 
 
59
#if CCTOOLS_OPSYS_SUNOS
 
60
#define statfs statvfs
 
61
#define fstatfs fstatvfs
 
62
#define statfs64 statvfs64
 
63
#define fstatfs64 fstatvfs64
 
64
#endif
 
65
 
 
66
#ifndef COPY_CSTAT
 
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;
 
82
#endif
 
83
 
 
84
INT64_T chirp_local_file_size( const char *path )
 
85
{
 
86
        struct chirp_stat info;
 
87
        if(chirp_local_stat(path,&info)==0) {
 
88
                return info.cst_size;
 
89
        } else {
 
90
                return -1;
 
91
        }
 
92
}
 
93
 
 
94
INT64_T chirp_local_fd_size( int fd )
 
95
{
 
96
        struct chirp_stat info;
 
97
        if(chirp_local_fstat(fd,&info)==0) {
 
98
                return info.cst_size;
 
99
        } else {
 
100
                return -1;
 
101
        }
 
102
}
 
103
 
 
104
INT64_T chirp_local_open( const char *path, INT64_T flags, INT64_T mode )
 
105
{
 
106
        mode = 0600 | (mode&0100);
 
107
        return open64(path,flags,(int)mode);
 
108
}
 
109
 
 
110
INT64_T chirp_local_close( int fd )
 
111
{
 
112
        return close(fd);
 
113
}
 
114
 
 
115
INT64_T chirp_local_pread( int fd, void *buffer, INT64_T length, INT64_T offset )
 
116
{
 
117
        INT64_T result;
 
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);
 
122
        }
 
123
        return result;
 
124
}
 
125
 
 
126
INT64_T chirp_local_sread( int fd, void *vbuffer, INT64_T length, INT64_T stride_length, INT64_T stride_skip, INT64_T offset )
 
127
{
 
128
        INT64_T total = 0;
 
129
        INT64_T actual = 0;
 
130
        char *buffer = vbuffer;
 
131
 
 
132
        if(stride_length<0 || stride_skip<0 || offset<0) {
 
133
                errno = EINVAL;
 
134
                return -1;
 
135
        }
 
136
 
 
137
        while(length>=stride_length) {
 
138
                actual = chirp_local_pread(fd,&buffer[total],stride_length,offset);
 
139
                if(actual>0) {
 
140
                        length -= actual;
 
141
                        total += actual;
 
142
                        offset += stride_skip;
 
143
                        if(actual==stride_length) {
 
144
                                continue;
 
145
                        } else {
 
146
                                break;
 
147
                        }
 
148
                } else {
 
149
                        break;
 
150
                }
 
151
        }
 
152
 
 
153
        if(total>0) {
 
154
                return total;
 
155
        } else {
 
156
                if(actual<0) {
 
157
                        return -1;
 
158
                } else {
 
159
                        return 0;
 
160
                }
 
161
        }
 
162
}
 
163
 
 
164
INT64_T chirp_local_pwrite( int fd, const void *buffer, INT64_T length, INT64_T offset )
 
165
{
 
166
        INT64_T result;
 
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);
 
171
        }
 
172
        return result;
 
173
}
 
174
 
 
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 )
 
176
{
 
177
        INT64_T total = 0;
 
178
        INT64_T actual = 0;
 
179
        const char *buffer = vbuffer;
 
180
 
 
181
        if(stride_length<0 || stride_skip<0 || offset<0) {
 
182
                errno = EINVAL;
 
183
                return -1;
 
184
        }
 
185
 
 
186
        while(length>=stride_length) {
 
187
                actual = chirp_local_pwrite(fd,&buffer[total],stride_length,offset);
 
188
                if(actual>0) {
 
189
                        length -= actual;
 
190
                        total += actual;
 
191
                        offset += stride_skip;
 
192
                        if(actual==stride_length) {
 
193
                                continue;
 
194
                        } else {
 
195
                                break;
 
196
                        }
 
197
                } else {
 
198
                        break;
 
199
                }
 
200
        }
 
201
 
 
202
        if(total>0) {
 
203
                return total;
 
204
        } else {
 
205
                if(actual<0) {
 
206
                        return -1;
 
207
                } else {
 
208
                        return 0;
 
209
                }
 
210
        }
 
211
}
 
212
 
 
213
INT64_T chirp_local_fstat( int fd, struct chirp_stat *buf )
 
214
{
 
215
        struct stat64 info;
 
216
        int result;
 
217
        result = fstat64(fd,&info);
 
218
        if(result==0) COPY_CSTAT(info,*buf);
 
219
        buf->cst_mode = buf->cst_mode & (~0077);
 
220
        return result;  
 
221
}
 
222
 
 
223
INT64_T chirp_local_fstatfs( int fd, struct chirp_statfs *buf )
 
224
{
 
225
        struct statfs64 info;
 
226
        int result;
 
227
        result = fstatfs64(fd,&info);
 
228
        if(result==0) {
 
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;
 
233
#else
 
234
                buf->f_type = info.f_type;
 
235
                buf->f_bsize = info.f_bsize;
 
236
#endif
 
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;
 
242
        }
 
243
        return result;
 
244
}
 
245
 
 
246
INT64_T chirp_local_fchown( int fd, INT64_T uid, INT64_T gid )
 
247
{
 
248
        // Changing file ownership is silently ignored,
 
249
        // because permissions are handled through the ACL model.
 
250
        return 0;
 
251
}
 
252
 
 
253
INT64_T chirp_local_fchmod( int fd, INT64_T mode )
 
254
{
 
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);
 
260
}
 
261
 
 
262
INT64_T chirp_local_ftruncate( int fd, INT64_T length )
 
263
{
 
264
        return ftruncate64(fd,length);
 
265
}
 
266
 
 
267
INT64_T chirp_local_fsync( int fd )
 
268
{
 
269
        return fsync(fd);
 
270
}
 
271
 
 
272
void *  chirp_local_opendir( const char *path )
 
273
{
 
274
        return opendir(path);
 
275
}
 
276
 
 
277
char *  chirp_local_readdir( void *dir )
 
278
{
 
279
        struct dirent *d;
 
280
        d = readdir(dir);
 
281
        if(d) {
 
282
                return d->d_name;
 
283
        } else {
 
284
                return 0;
 
285
        }
 
286
}
 
287
 
 
288
void    chirp_local_closedir( void *dir )
 
289
{
 
290
        closedir(dir);
 
291
}
 
292
 
 
293
INT64_T chirp_local_getfile( const char *path, struct link *link, time_t stoptime )
 
294
{
 
295
        int fd;
 
296
        INT64_T result;
 
297
        struct chirp_stat info;
 
298
        
 
299
        result = chirp_local_stat(path,&info);
 
300
        if(result<0) return result;
 
301
 
 
302
        if(S_ISDIR(info.cst_mode)) {
 
303
                errno = EISDIR;
 
304
                return -1;
 
305
        }
 
306
 
 
307
        if(S_ISFIFO(info.cst_mode)) {
 
308
                errno = ESPIPE;
 
309
                return -1;
 
310
        }
 
311
 
 
312
        fd = chirp_local_open(path,O_RDONLY,0);
 
313
        if(fd>=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);
 
318
        } else {
 
319
                result = -1;
 
320
        }
 
321
 
 
322
        return result;
 
323
}
 
324
 
 
325
INT64_T chirp_local_putfile( const char *path, struct link *link, INT64_T length, INT64_T mode, time_t stoptime )
 
326
{
 
327
        int fd;
 
328
        INT64_T result;
 
329
 
 
330
        mode = 0600 | (mode&0100);
 
331
 
 
332
        fd = chirp_local_open(path,O_WRONLY|O_CREAT|O_TRUNC,(int)mode);
 
333
        if(fd>=0) {
 
334
                link_putliteral(link,"0\n",stoptime);
 
335
                result = link_stream_to_fd(link,fd,length,stoptime);
 
336
                if(result!=length) {
 
337
                        if(result>=0) link_soak(link,length-result,stoptime);
 
338
                        result = -1;
 
339
                }
 
340
                chirp_local_close(fd);
 
341
        } else {
 
342
                result = -1;
 
343
        }
 
344
        return result;
 
345
}
 
346
 
 
347
INT64_T chirp_local_mkfifo( const char *path )
 
348
{
 
349
        return mknod(path,0700|S_IFIFO,0);
 
350
}
 
351
 
 
352
INT64_T chirp_local_unlink( const char *path )
 
353
{
 
354
        int result = unlink(path);
 
355
 
 
356
        /*
 
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.
 
360
        */
 
361
 
 
362
        if(result<0 && errno==EPERM) {
 
363
                struct stat64 info;
 
364
                result = stat64(path,&info);
 
365
                if(result==0 && S_ISDIR(info.st_mode)) {
 
366
                        result = -1;
 
367
                        errno = EISDIR;
 
368
                } else {
 
369
                        result = -1;
 
370
                        errno = EPERM;
 
371
                }
 
372
        }
 
373
 
 
374
        return result;
 
375
}
 
376
 
 
377
INT64_T chirp_local_rename( const char *path, const char *newpath )
 
378
{
 
379
        return rename(path,newpath);
 
380
}
 
381
 
 
382
INT64_T chirp_local_link( const char *path, const char *newpath )
 
383
{
 
384
        return link(path,newpath);
 
385
}
 
386
 
 
387
INT64_T chirp_local_symlink( const char *path, const char *newpath )
 
388
{
 
389
        return symlink(path,newpath);
 
390
}
 
391
 
 
392
INT64_T chirp_local_readlink( const char *path, char *buf, INT64_T length )
 
393
{
 
394
        return readlink(path,buf,length);
 
395
}
 
396
 
 
397
INT64_T chirp_local_chdir( const char *path)
 
398
{
 
399
  return chdir(path);
 
400
}
 
401
 
 
402
INT64_T chirp_local_mkdir( const char *path, INT64_T mode )
 
403
{
 
404
        return mkdir(path,0700);
 
405
}
 
406
 
 
407
/*
 
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.
 
412
*/
 
413
 
 
414
INT64_T chirp_local_rmdir( const char *path )
 
415
{
 
416
        void *dir;
 
417
        char *d;
 
418
        int empty = 1;
 
419
 
 
420
        dir = chirp_local_opendir(path);
 
421
        if(dir) {
 
422
                while((d=chirp_local_readdir(dir))) {
 
423
                        if(!strcmp(d,".")) continue;
 
424
                        if(!strcmp(d,"..")) continue;
 
425
                        if(!strncmp(d,".__",3)) continue;
 
426
                        empty = 0;
 
427
                        break;
 
428
                }
 
429
                chirp_local_closedir(dir);
 
430
 
 
431
                if(empty) {
 
432
                        if(delete_dir(path)) {
 
433
                                return 0;
 
434
                        } else {
 
435
                                return -1;
 
436
                        }
 
437
                } else {
 
438
                        errno = ENOTEMPTY;
 
439
                        return -1;
 
440
                }               
 
441
        } else {
 
442
                return -1;
 
443
        }
 
444
}
 
445
 
 
446
INT64_T chirp_local_stat( const char *path, struct chirp_stat *buf )
 
447
{
 
448
        struct stat64 info;
 
449
        int result;
 
450
        result = stat64(path,&info);
 
451
        if(result==0) COPY_CSTAT(info,*buf);
 
452
        return result;
 
453
}
 
454
 
 
455
INT64_T chirp_local_lstat( const char *path, struct chirp_stat *buf )
 
456
{
 
457
        struct stat64 info;
 
458
        int result;
 
459
        result = lstat64(path,&info);
 
460
        if(result==0) COPY_CSTAT(info,*buf);
 
461
        return result;
 
462
}
 
463
 
 
464
INT64_T chirp_local_statfs( const char *path, struct chirp_statfs *buf )
 
465
{
 
466
        struct statfs64 info;
 
467
        int result;
 
468
        result = statfs64(path,&info);
 
469
        if(result==0) {
 
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;
 
474
#else
 
475
                buf->f_type = info.f_type;
 
476
                buf->f_bsize = info.f_bsize;
 
477
#endif
 
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;
 
483
        }
 
484
        return result;
 
485
}
 
486
 
 
487
INT64_T chirp_local_access( const char *path, INT64_T mode )
 
488
{
 
489
        return access(path,mode);
 
490
}
 
491
 
 
492
INT64_T chirp_local_chmod( const char *path, INT64_T mode )
 
493
{
 
494
        struct chirp_stat info;
 
495
 
 
496
        int result = chirp_local_stat(path,&info);
 
497
        if(result<0) return result;
 
498
 
 
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.
 
502
 
 
503
        if(S_ISDIR(info.cst_mode)) {
 
504
                // On a directory, the user cannot set the execute bit.
 
505
                mode = 0700 | (mode&0077);
 
506
        } else {
 
507
                // On a file, the user can set the execute bit.
 
508
                mode = 0600 | (mode&0177);
 
509
        }
 
510
 
 
511
        return chmod(path,mode);
 
512
}
 
513
 
 
514
INT64_T chirp_local_chown( const char *path, INT64_T uid, INT64_T gid )
 
515
{
 
516
        // Changing file ownership is silently ignored,
 
517
        // because permissions are handled through the ACL model.
 
518
        return 0;
 
519
}
 
520
 
 
521
INT64_T chirp_local_lchown( const char *path, INT64_T uid, INT64_T gid )
 
522
{
 
523
        // Changing file ownership is silently ignored,
 
524
        // because permissions are handled through the ACL model.
 
525
        return 0;
 
526
}
 
527
 
 
528
INT64_T chirp_local_truncate( const char *path, INT64_T length )
 
529
{
 
530
        return truncate64(path,length);
 
531
}
 
532
 
 
533
INT64_T chirp_local_utime( const char *path, time_t actime, time_t modtime )
 
534
{
 
535
        struct utimbuf ut;
 
536
        ut.actime = actime;
 
537
        ut.modtime = modtime;
 
538
        return utime(path,&ut);
 
539
}
 
540
 
 
541
INT64_T chirp_local_md5( const char *path, unsigned char digest[16] )
 
542
{
 
543
        return md5_file(path,digest);
 
544
}
 
545
 
 
546
INT64_T chirp_local_init (const char *path)
 
547
{
 
548
  return 0;
 
549
}
 
550
 
 
551
INT64_T chirp_local_destroy (void)
 
552
{
 
553
  return 0;
 
554
}
 
555
 
 
556
struct chirp_filesystem chirp_local_fs = {
 
557
        chirp_local_init,
 
558
    chirp_local_destroy,
 
559
 
 
560
        chirp_local_open,
 
561
        chirp_local_close,
 
562
        chirp_local_pread,
 
563
        chirp_local_pwrite,
 
564
        chirp_local_sread,
 
565
        chirp_local_swrite,
 
566
        chirp_local_fstat,
 
567
        chirp_local_fstatfs,
 
568
        chirp_local_fchown,
 
569
        chirp_local_fchmod,
 
570
        chirp_local_ftruncate,
 
571
        chirp_local_fsync,
 
572
 
 
573
        chirp_local_opendir,
 
574
        chirp_local_readdir,
 
575
        chirp_local_closedir,
 
576
 
 
577
        chirp_local_getfile,
 
578
        chirp_local_putfile,
 
579
 
 
580
        chirp_local_mkfifo,
 
581
        chirp_local_unlink,
 
582
        chirp_local_rename,
 
583
        chirp_local_link,
 
584
        chirp_local_symlink,
 
585
        chirp_local_readlink,
 
586
        chirp_local_chdir,
 
587
        chirp_local_mkdir,
 
588
        chirp_local_rmdir,
 
589
        chirp_local_stat,
 
590
        chirp_local_lstat,
 
591
        chirp_local_statfs,
 
592
        chirp_local_access,
 
593
        chirp_local_chmod,
 
594
        chirp_local_chown,
 
595
        chirp_local_lchown,
 
596
        chirp_local_truncate,
 
597
        chirp_local_utime,
 
598
        chirp_local_md5,
 
599
 
 
600
        chirp_local_file_size,
 
601
        chirp_local_fd_size,
 
602
};