00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #ifdef _WIN32
00016 #include "missing/file.h"
00017 #endif
00018
00019 #include "ruby.h"
00020 #include "rubyio.h"
00021 #include "rubysig.h"
00022 #include "util.h"
00023 #include "dln.h"
00024
00025 #ifdef HAVE_UNISTD_H
00026 #include <unistd.h>
00027 #endif
00028
00029 #ifdef HAVE_SYS_FILE_H
00030 # include <sys/file.h>
00031 #else
00032 int flock (int, int);
00033 #endif
00034
00035 #ifdef HAVE_SYS_PARAM_H
00036 # include <sys/param.h>
00037 #endif
00038 #ifndef MAXPATHLEN
00039 # define MAXPATHLEN 1024
00040 #endif
00041
00042 #include <time.h>
00043
00044 VALUE rb_time_new (time_t, time_t);
00045
00046 #ifdef HAVE_UTIME_H
00047 #include <utime.h>
00048 #elif defined HAVE_SYS_UTIME_H
00049 #include <sys/utime.h>
00050 #endif
00051
00052 #ifdef HAVE_PWD_H
00053 #include <pwd.h>
00054 #endif
00055
00056 #ifndef HAVE_STRING_H
00057 char *strrchr (const char*,const char);
00058 #endif
00059
00060 #include <sys/types.h>
00061 #include <sys/stat.h>
00062
00063 #ifdef HAVE_SYS_MKDEV_H
00064 #include <sys/mkdev.h>
00065 #endif
00066
00067 #if !defined HAVE_LSTAT && !defined lstat
00068 #define lstat stat
00069 #endif
00070 #if !HAVE_FSEEKO && !defined(fseeko)
00071 # define fseeko fseek
00072 #endif
00073
00074 #ifdef __BEOS__
00075 static int
00076 be_chown(const char *path, uid_t owner, gid_t group)
00077 {
00078 if (owner == -1 || group == -1) {
00079 struct stat st;
00080 if (stat(path, &st) < 0) return -1;
00081 if (owner == -1) owner = st.st_uid;
00082 if (group == -1) group = st.st_gid;
00083 }
00084 return chown(path, owner, group);
00085 }
00086 #define chown be_chown
00087 static int
00088 be_fchown(int fd, uid_t owner, gid_t group)
00089 {
00090 if (owner == -1 || group == -1) {
00091 struct stat st;
00092 if (fstat(fd, &st) < 0) return -1;
00093 if (owner == -1) owner = st.st_uid;
00094 if (group == -1) group = st.st_gid;
00095 }
00096 return fchown(fd, owner, group);
00097 }
00098 #define fchown be_fchown
00099 #endif
00100
00101 VALUE rb_cFile;
00102 VALUE rb_mFileTest;
00103 static VALUE rb_cStat;
00104
00105 static long apply2files (void (*(const char *, void *), VALUE, void *));
00106 static long
00107 apply2files(func, vargs, arg)
00108 void (*func)(const char *, void *);
00109 VALUE vargs;
00110 void *arg;
00111 {
00112 long i;
00113 VALUE path;
00114 struct RArray *args = RARRAY(vargs);
00115
00116 for (i=0; i<args->len; i++) {
00117 path = args->ptr[i];
00118 SafeStringValue(path);
00119 (*func)(StringValueCStr(path), arg);
00120 }
00121
00122 return args->len;
00123 }
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137 static VALUE
00138 rb_file_path(obj)
00139 VALUE obj;
00140 {
00141 OpenFile *fptr;
00142
00143 fptr = RFILE(rb_io_taint_check(obj))->fptr;
00144 rb_io_check_initialized(fptr);
00145 if (!fptr->path) return Qnil;
00146 return rb_tainted_str_new2(fptr->path);
00147 }
00148
00149 static VALUE
00150 stat_new_0(klass, st)
00151 VALUE klass;
00152 struct stat *st;
00153 {
00154 struct stat *nst = 0;
00155
00156 if (st) {
00157 nst = ALLOC(struct stat);
00158 *nst = *st;
00159 }
00160 return Data_Wrap_Struct(klass, NULL, free, nst);
00161 }
00162
00163 static VALUE
00164 stat_new(st)
00165 struct stat *st;
00166 {
00167 return stat_new_0(rb_cStat, st);
00168 }
00169
00170 static struct stat*
00171 get_stat(self)
00172 VALUE self;
00173 {
00174 struct stat* st;
00175 Data_Get_Struct(self, struct stat, st);
00176 if (!st) rb_raise(rb_eTypeError, "uninitialized File::Stat");
00177 return st;
00178 }
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193 static VALUE
00194 rb_stat_cmp(self, other)
00195 VALUE self, other;
00196 {
00197 if (rb_obj_is_kind_of(other, rb_obj_class(self))) {
00198 time_t t1 = get_stat(self)->st_mtime;
00199 time_t t2 = get_stat(other)->st_mtime;
00200 if (t1 == t2)
00201 return INT2FIX(0);
00202 else if (t1 < t2)
00203 return INT2FIX(-1);
00204 else
00205 return INT2FIX(1);
00206 }
00207 return Qnil;
00208 }
00209
00210 static VALUE rb_stat_dev (VALUE);
00211 static VALUE rb_stat_ino (VALUE);
00212 static VALUE rb_stat_mode (VALUE);
00213 static VALUE rb_stat_nlink (VALUE);
00214 static VALUE rb_stat_uid (VALUE);
00215 static VALUE rb_stat_gid (VALUE);
00216 static VALUE rb_stat_rdev (VALUE);
00217 static VALUE rb_stat_size (VALUE);
00218 static VALUE rb_stat_blksize (VALUE);
00219 static VALUE rb_stat_blocks (VALUE);
00220 static VALUE rb_stat_atime (VALUE);
00221 static VALUE rb_stat_mtime (VALUE);
00222 static VALUE rb_stat_ctime (VALUE);
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234 static VALUE
00235 rb_stat_dev(self)
00236 VALUE self;
00237 {
00238 return INT2NUM(get_stat(self)->st_dev);
00239 }
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 static VALUE
00253 rb_stat_dev_major(self)
00254 VALUE self;
00255 {
00256 #if defined(major)
00257 long dev = get_stat(self)->st_dev;
00258 return ULONG2NUM(major(dev));
00259 #else
00260 return Qnil;
00261 #endif
00262 }
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275 static VALUE
00276 rb_stat_dev_minor(self)
00277 VALUE self;
00278 {
00279 #if defined(minor)
00280 long dev = get_stat(self)->st_dev;
00281 return ULONG2NUM(minor(dev));
00282 #else
00283 return Qnil;
00284 #endif
00285 }
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298 static VALUE
00299 rb_stat_ino(self)
00300 VALUE self;
00301 {
00302 #ifdef HUGE_ST_INO
00303 return ULL2NUM(get_stat(self)->st_ino);
00304 #else
00305 return ULONG2NUM(get_stat(self)->st_ino);
00306 #endif
00307 }
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 static VALUE
00323 rb_stat_mode(self)
00324 VALUE self;
00325 {
00326 #ifdef __BORLANDC__
00327 return UINT2NUM((unsigned short)(get_stat(self)->st_mode));
00328 #else
00329 return UINT2NUM(get_stat(self)->st_mode);
00330 #endif
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345 static VALUE
00346 rb_stat_nlink(self)
00347 VALUE self;
00348 {
00349 return UINT2NUM(get_stat(self)->st_nlink);
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363 static VALUE
00364 rb_stat_uid(self)
00365 VALUE self;
00366 {
00367 return UINT2NUM(get_stat(self)->st_uid);
00368 }
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 static VALUE
00381 rb_stat_gid(self)
00382 VALUE self;
00383 {
00384 return UINT2NUM(get_stat(self)->st_gid);
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 static VALUE
00401 rb_stat_rdev(self)
00402 VALUE self;
00403 {
00404 #ifdef HAVE_ST_RDEV
00405 return ULONG2NUM(get_stat(self)->st_rdev);
00406 #else
00407 return Qnil;
00408 #endif
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 static VALUE
00423 rb_stat_rdev_major(self)
00424 VALUE self;
00425 {
00426 #if defined(HAVE_ST_RDEV) && defined(major)
00427 long rdev = get_stat(self)->st_rdev;
00428 return ULONG2NUM(major(rdev));
00429 #else
00430 return Qnil;
00431 #endif
00432 }
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445 static VALUE
00446 rb_stat_rdev_minor(self)
00447 VALUE self;
00448 {
00449 #if defined(HAVE_ST_RDEV) && defined(minor)
00450 long rdev = get_stat(self)->st_rdev;
00451 return ULONG2NUM(minor(rdev));
00452 #else
00453 return Qnil;
00454 #endif
00455 }
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 static VALUE
00467 rb_stat_size(self)
00468 VALUE self;
00469 {
00470 return OFFT2NUM(get_stat(self)->st_size);
00471 }
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484 static VALUE
00485 rb_stat_blksize(self)
00486 VALUE self;
00487 {
00488 #ifdef HAVE_ST_BLKSIZE
00489 return ULONG2NUM(get_stat(self)->st_blksize);
00490 #else
00491 return Qnil;
00492 #endif
00493 }
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506 static VALUE
00507 rb_stat_blocks(self)
00508 VALUE self;
00509 {
00510 #ifdef HAVE_ST_BLOCKS
00511 return ULONG2NUM(get_stat(self)->st_blocks);
00512 #else
00513 return Qnil;
00514 #endif
00515 }
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529 static VALUE
00530 rb_stat_atime(self)
00531 VALUE self;
00532 {
00533 return rb_time_new(get_stat(self)->st_atime, 0);
00534 }
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546 static VALUE
00547 rb_stat_mtime(self)
00548 VALUE self;
00549 {
00550 return rb_time_new(get_stat(self)->st_mtime, 0);
00551 }
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 static VALUE
00566 rb_stat_ctime(self)
00567 VALUE self;
00568 {
00569 return rb_time_new(get_stat(self)->st_ctime, 0);
00570 }
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586 static VALUE
00587 rb_stat_inspect(self)
00588 VALUE self;
00589 {
00590 VALUE str;
00591 int i;
00592 static const struct {
00593 const char *name;
00594 VALUE (*func)(VALUE);
00595 } member[] = {
00596 {"dev", rb_stat_dev},
00597 {"ino", rb_stat_ino},
00598 {"mode", rb_stat_mode},
00599 {"nlink", rb_stat_nlink},
00600 {"uid", rb_stat_uid},
00601 {"gid", rb_stat_gid},
00602 {"rdev", rb_stat_rdev},
00603 {"size", rb_stat_size},
00604 {"blksize", rb_stat_blksize},
00605 {"blocks", rb_stat_blocks},
00606 {"atime", rb_stat_atime},
00607 {"mtime", rb_stat_mtime},
00608 {"ctime", rb_stat_ctime},
00609 };
00610
00611 str = rb_str_buf_new2("#<");
00612 rb_str_buf_cat2(str, rb_obj_classname(self));
00613 rb_str_buf_cat2(str, " ");
00614
00615 for (i = 0; i < sizeof(member)/sizeof(member[0]); i++) {
00616 VALUE v;
00617
00618 if (i > 0) {
00619 rb_str_buf_cat2(str, ", ");
00620 }
00621 rb_str_buf_cat2(str, member[i].name);
00622 rb_str_buf_cat2(str, "=");
00623 v = (*member[i].func)(self);
00624 if (i == 2) {
00625 char buf[32];
00626
00627 sprintf(buf, "0%lo", NUM2ULONG(v));
00628 rb_str_buf_cat2(str, buf);
00629 }
00630 else if (i == 0 || i == 6) {
00631 char buf[32];
00632
00633 sprintf(buf, "0x%lx", NUM2ULONG(v));
00634 rb_str_buf_cat2(str, buf);
00635 }
00636 else {
00637 rb_str_append(str, rb_inspect(v));
00638 }
00639 }
00640 rb_str_buf_cat2(str, ">");
00641 OBJ_INFECT(str, self);
00642
00643 return str;
00644 }
00645
00646 static int
00647 rb_stat(file, st)
00648 VALUE file;
00649 struct stat *st;
00650 {
00651 VALUE tmp;
00652
00653 tmp = rb_check_convert_type(file, T_FILE, "IO", "to_io");
00654 if (!NIL_P(tmp)) {
00655 OpenFile *fptr;
00656
00657 rb_secure(2);
00658 GetOpenFile(tmp, fptr);
00659 return fstat(fileno(fptr->f), st);
00660 }
00661 SafeStringValue(file);
00662 return stat(StringValueCStr(file), st);
00663 }
00664
00665 #ifdef _WIN32
00666 static HANDLE
00667 w32_io_info(file, st)
00668 VALUE *file;
00669 BY_HANDLE_FILE_INFORMATION *st;
00670 {
00671 VALUE tmp;
00672 HANDLE f, ret = 0;
00673
00674 tmp = rb_check_convert_type(*file, T_FILE, "IO", "to_io");
00675 if (!NIL_P(tmp)) {
00676 OpenFile *fptr;
00677
00678 GetOpenFile(tmp, fptr);
00679 f = (HANDLE)rb_w32_get_osfhandle(fileno(fptr->f));
00680 if (f == (HANDLE)-1) return INVALID_HANDLE_VALUE;
00681 }
00682 else {
00683 SafeStringValue(*file);
00684 f = CreateFile(StringValueCStr(*file), 0,
00685 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
00686 rb_w32_iswin95() ? 0 : FILE_FLAG_BACKUP_SEMANTICS, NULL);
00687 if (f == INVALID_HANDLE_VALUE) return f;
00688 ret = f;
00689 }
00690 if (GetFileType(f) == FILE_TYPE_DISK) {
00691 ZeroMemory(st, sizeof(*st));
00692 if (GetFileInformationByHandle(f, st)) return ret;
00693 }
00694 if (ret) CloseHandle(ret);
00695 return INVALID_HANDLE_VALUE;
00696 }
00697 #endif
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710 static VALUE
00711 rb_file_s_stat(klass, fname)
00712 VALUE klass, fname;
00713 {
00714 struct stat st;
00715
00716 SafeStringValue(fname);
00717 if (rb_stat(fname, &st) < 0) {
00718 rb_sys_fail(StringValueCStr(fname));
00719 }
00720 return stat_new(&st);
00721 }
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738 static VALUE
00739 rb_io_stat(obj)
00740 VALUE obj;
00741 {
00742 OpenFile *fptr;
00743 struct stat st;
00744
00745 GetOpenFile(obj, fptr);
00746 if (fstat(fileno(fptr->f), &st) == -1) {
00747 rb_sys_fail(fptr->path);
00748 }
00749 return stat_new(&st);
00750 }
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766 static VALUE
00767 rb_file_s_lstat(klass, fname)
00768 VALUE klass, fname;
00769 {
00770 #ifdef HAVE_LSTAT
00771 struct stat st;
00772
00773 SafeStringValue(fname);
00774 if (lstat(StringValueCStr(fname), &st) == -1) {
00775 rb_sys_fail(RSTRING(fname)->ptr);
00776 }
00777 return stat_new(&st);
00778 #else
00779 return rb_file_s_stat(klass, fname);
00780 #endif
00781 }
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798 static VALUE
00799 rb_file_lstat(obj)
00800 VALUE obj;
00801 {
00802 #ifdef HAVE_LSTAT
00803 OpenFile *fptr;
00804 struct stat st;
00805
00806 rb_secure(2);
00807 GetOpenFile(obj, fptr);
00808 if (!fptr->path) return Qnil;
00809 if (lstat(fptr->path, &st) == -1) {
00810 rb_sys_fail(fptr->path);
00811 }
00812 return stat_new(&st);
00813 #else
00814 return rb_io_stat(obj);
00815 #endif
00816 }
00817
00818 static int
00819 group_member(gid)
00820 GETGROUPS_T gid;
00821 {
00822 #ifndef _WIN32
00823 if (getgid() == gid)
00824 return Qtrue;
00825
00826 # ifdef HAVE_GETGROUPS
00827 # ifndef NGROUPS
00828 # ifdef NGROUPS_MAX
00829 # define NGROUPS NGROUPS_MAX
00830 # else
00831 # define NGROUPS 32
00832 # endif
00833 # endif
00834 {
00835 GETGROUPS_T gary[NGROUPS];
00836 int anum;
00837
00838 anum = getgroups(NGROUPS, gary);
00839 while (--anum >= 0)
00840 if (gary[anum] == gid)
00841 return Qtrue;
00842 }
00843 # endif
00844 #endif
00845 return Qfalse;
00846 }
00847
00848 #ifndef S_IXUGO
00849 # define S_IXUGO (S_IXUSR | S_IXGRP | S_IXOTH)
00850 #endif
00851
00852 int
00853 eaccess(path, mode)
00854 const char *path;
00855 int mode;
00856 {
00857 #if defined(S_IXGRP) && !defined(_WIN32) && !defined(__CYGWIN__)
00858 struct stat st;
00859 int euid;
00860
00861 if (stat(path, &st) < 0) return -1;
00862
00863 euid = geteuid();
00864
00865 if (euid == 0) {
00866
00867 if (!(mode & X_OK))
00868 return 0;
00869
00870
00871
00872 if (st.st_mode & S_IXUGO)
00873 return 0;
00874
00875 return -1;
00876 }
00877
00878 if (st.st_uid == euid)
00879 mode <<= 6;
00880 else if (getegid() == st.st_gid || group_member(st.st_gid))
00881 mode <<= 3;
00882
00883 if ((st.st_mode & mode) == mode) return 0;
00884
00885 return -1;
00886 #else
00887 return access(path, mode);
00888 #endif
00889 }
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912
00913 static VALUE
00914 test_d(obj, fname)
00915 VALUE obj, fname;
00916 {
00917 #ifndef S_ISDIR
00918 # define S_ISDIR(m) ((m & S_IFMT) == S_IFDIR)
00919 #endif
00920
00921 struct stat st;
00922
00923 if (rb_stat(fname, &st) < 0) return Qfalse;
00924 if (S_ISDIR(st.st_mode)) return Qtrue;
00925 return Qfalse;
00926 }
00927
00928
00929
00930
00931
00932
00933
00934
00935 static VALUE
00936 test_p(obj, fname)
00937 VALUE obj, fname;
00938 {
00939 #ifdef S_IFIFO
00940 # ifndef S_ISFIFO
00941 # define S_ISFIFO(m) ((m & S_IFMT) == S_IFIFO)
00942 # endif
00943
00944 struct stat st;
00945
00946 if (rb_stat(fname, &st) < 0) return Qfalse;
00947 if (S_ISFIFO(st.st_mode)) return Qtrue;
00948
00949 #endif
00950 return Qfalse;
00951 }
00952
00953
00954
00955
00956
00957
00958
00959
00960 static VALUE
00961 test_l(obj, fname)
00962 VALUE obj, fname;
00963 {
00964 #ifndef S_ISLNK
00965 # ifdef _S_ISLNK
00966 # define S_ISLNK(m) _S_ISLNK(m)
00967 # elif defined __BORLANDC__
00968 # ifdef _S_IFLNK
00969 # define S_ISLNK(m) (((unsigned short)(m) & S_IFMT) == _S_IFLNK)
00970 # else
00971 # ifdef S_IFLNK
00972 # define S_ISLNK(m) (((unsigned short)(m) & S_IFMT) == S_IFLNK)
00973 # endif
00974 # endif
00975 # else
00976 # ifdef _S_IFLNK
00977 # define S_ISLNK(m) ((m & S_IFMT) == _S_IFLNK)
00978 # else
00979 # ifdef S_IFLNK
00980 # define S_ISLNK(m) ((m & S_IFMT) == S_IFLNK)
00981 # endif
00982 # endif
00983 # endif
00984 #endif
00985
00986 #ifdef S_ISLNK
00987 struct stat st;
00988
00989 SafeStringValue(fname);
00990 if (lstat(StringValueCStr(fname), &st) < 0) return Qfalse;
00991 if (S_ISLNK(st.st_mode)) return Qtrue;
00992 #endif
00993
00994 return Qfalse;
00995 }
00996
00997
00998
00999
01000
01001
01002
01003
01004 static VALUE
01005 test_S(obj, fname)
01006 VALUE obj, fname;
01007 {
01008 #ifndef S_ISSOCK
01009 # ifdef _S_ISSOCK
01010 # define S_ISSOCK(m) _S_ISSOCK(m)
01011 # elif defined __BORLANDC__
01012 # ifdef _S_IFSOCK
01013 # define S_ISSOCK(m) (((unsigned short)(m) & S_IFMT) == _S_IFSOCK)
01014 # else
01015 # ifdef S_IFSOCK
01016 # define S_ISSOCK(m) (((unsigned short)(m) & S_IFMT) == S_IFSOCK)
01017 # endif
01018 # endif
01019 # else
01020 # ifdef _S_IFSOCK
01021 # define S_ISSOCK(m) ((m & S_IFMT) == _S_IFSOCK)
01022 # else
01023 # ifdef S_IFSOCK
01024 # define S_ISSOCK(m) ((m & S_IFMT) == S_IFSOCK)
01025 # endif
01026 # endif
01027 # endif
01028 #endif
01029
01030 #ifdef S_ISSOCK
01031 struct stat st;
01032
01033 if (rb_stat(fname, &st) < 0) return Qfalse;
01034 if (S_ISSOCK(st.st_mode)) return Qtrue;
01035
01036 #endif
01037 return Qfalse;
01038 }
01039
01040
01041
01042
01043
01044
01045
01046
01047 static VALUE
01048 test_b(obj, fname)
01049 VALUE obj, fname;
01050 {
01051 #ifndef S_ISBLK
01052 # ifdef S_IFBLK
01053 # define S_ISBLK(m) ((m & S_IFMT) == S_IFBLK)
01054 # else
01055 # define S_ISBLK(m) (0)
01056 # endif
01057 #endif
01058
01059 #ifdef S_ISBLK
01060 struct stat st;
01061
01062 if (rb_stat(fname, &st) < 0) return Qfalse;
01063 if (S_ISBLK(st.st_mode)) return Qtrue;
01064
01065 #endif
01066 return Qfalse;
01067 }
01068
01069
01070
01071
01072
01073
01074
01075 static VALUE
01076 test_c(obj, fname)
01077 VALUE obj, fname;
01078 {
01079 #ifndef S_ISCHR
01080 # define S_ISCHR(m) ((m & S_IFMT) == S_IFCHR)
01081 #endif
01082
01083 struct stat st;
01084
01085 if (rb_stat(fname, &st) < 0) return Qfalse;
01086 if (S_ISCHR(st.st_mode)) return Qtrue;
01087
01088 return Qfalse;
01089 }
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100 static VALUE
01101 test_e(obj, fname)
01102 VALUE obj, fname;
01103 {
01104 struct stat st;
01105
01106 if (rb_stat(fname, &st) < 0) return Qfalse;
01107 return Qtrue;
01108 }
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118 static VALUE
01119 test_r(obj, fname)
01120 VALUE obj, fname;
01121 {
01122 SafeStringValue(fname);
01123 if (eaccess(StringValueCStr(fname), R_OK) < 0) return Qfalse;
01124 return Qtrue;
01125 }
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135 static VALUE
01136 test_R(obj, fname)
01137 VALUE obj, fname;
01138 {
01139 SafeStringValue(fname);
01140 if (access(StringValueCStr(fname), R_OK) < 0) return Qfalse;
01141 return Qtrue;
01142 }
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153 static VALUE
01154 test_w(obj, fname)
01155 VALUE obj, fname;
01156 {
01157 SafeStringValue(fname);
01158 if (eaccess(StringValueCStr(fname), W_OK) < 0) return Qfalse;
01159 return Qtrue;
01160 }
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170 static VALUE
01171 test_W(obj, fname)
01172 VALUE obj, fname;
01173 {
01174 SafeStringValue(fname);
01175 if (access(StringValueCStr(fname), W_OK) < 0) return Qfalse;
01176 return Qtrue;
01177 }
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187 static VALUE
01188 test_x(obj, fname)
01189 VALUE obj, fname;
01190 {
01191 SafeStringValue(fname);
01192 if (eaccess(StringValueCStr(fname), X_OK) < 0) return Qfalse;
01193 return Qtrue;
01194 }
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204 static VALUE
01205 test_X(obj, fname)
01206 VALUE obj, fname;
01207 {
01208 SafeStringValue(fname);
01209 if (access(StringValueCStr(fname), X_OK) < 0) return Qfalse;
01210 return Qtrue;
01211 }
01212
01213 #ifndef S_ISREG
01214 # define S_ISREG(m) ((m & S_IFMT) == S_IFREG)
01215 #endif
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225 static VALUE
01226 test_f(obj, fname)
01227 VALUE obj, fname;
01228 {
01229 struct stat st;
01230
01231 if (rb_stat(fname, &st) < 0) return Qfalse;
01232 if (S_ISREG(st.st_mode)) return Qtrue;
01233 return Qfalse;
01234 }
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244 static VALUE
01245 test_z(obj, fname)
01246 VALUE obj, fname;
01247 {
01248 struct stat st;
01249
01250 if (rb_stat(fname, &st) < 0) return Qfalse;
01251 if (st.st_size == 0) return Qtrue;
01252 return Qfalse;
01253 }
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263 static VALUE
01264 test_s(obj, fname)
01265 VALUE obj, fname;
01266 {
01267 struct stat st;
01268
01269 if (rb_stat(fname, &st) < 0) return Qnil;
01270 if (st.st_size == 0) return Qnil;
01271 return OFFT2NUM(st.st_size);
01272 }
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283 static VALUE
01284 test_owned(obj, fname)
01285 VALUE obj, fname;
01286 {
01287 struct stat st;
01288
01289 if (rb_stat(fname, &st) < 0) return Qfalse;
01290 if (st.st_uid == geteuid()) return Qtrue;
01291 return Qfalse;
01292 }
01293
01294 static VALUE
01295 test_rowned(obj, fname)
01296 VALUE obj, fname;
01297 {
01298 struct stat st;
01299
01300 if (rb_stat(fname, &st) < 0) return Qfalse;
01301 if (st.st_uid == getuid()) return Qtrue;
01302 return Qfalse;
01303 }
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314 static VALUE
01315 test_grpowned(obj, fname)
01316 VALUE obj, fname;
01317 {
01318 #ifndef _WIN32
01319 struct stat st;
01320
01321 if (rb_stat(fname, &st) < 0) return Qfalse;
01322 if (st.st_gid == getegid()) return Qtrue;
01323 #endif
01324 return Qfalse;
01325 }
01326
01327 #if defined(S_ISUID) || defined(S_ISGID) || defined(S_ISVTX)
01328 static VALUE
01329 check3rdbyte(fname, mode)
01330 VALUE fname;
01331 int mode;
01332 {
01333 struct stat st;
01334
01335 SafeStringValue(fname);
01336 if (stat(StringValueCStr(fname), &st) < 0) return Qfalse;
01337 if (st.st_mode & mode) return Qtrue;
01338 return Qfalse;
01339 }
01340 #endif
01341
01342
01343
01344
01345
01346
01347
01348
01349 static VALUE
01350 test_suid(obj, fname)
01351 VALUE obj, fname;
01352 {
01353 #ifdef S_ISUID
01354 return check3rdbyte(fname, S_ISUID);
01355 #else
01356 return Qfalse;
01357 #endif
01358 }
01359
01360
01361
01362
01363
01364
01365
01366
01367 static VALUE
01368 test_sgid(obj, fname)
01369 VALUE obj, fname;
01370 {
01371 #ifdef S_ISGID
01372 return check3rdbyte(fname, S_ISGID);
01373 #else
01374 return Qfalse;
01375 #endif
01376 }
01377
01378
01379
01380
01381
01382
01383
01384
01385 static VALUE
01386 test_sticky(obj, fname)
01387 VALUE obj, fname;
01388 {
01389 #ifdef S_ISVTX
01390 return check3rdbyte(fname, S_ISVTX);
01391 #else
01392 return Qnil;
01393 #endif
01394 }
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413 static VALUE
01414 test_identical(obj, fname1, fname2)
01415 VALUE obj, fname1, fname2;
01416 {
01417 #ifndef DOSISH
01418 struct stat st1, st2;
01419
01420 if (rb_stat(fname1, &st1) < 0) return Qfalse;
01421 if (rb_stat(fname2, &st2) < 0) return Qfalse;
01422 if (st1.st_dev != st2.st_dev) return Qfalse;
01423 if (st1.st_ino != st2.st_ino) return Qfalse;
01424 #else
01425 #ifdef _WIN32
01426 BY_HANDLE_FILE_INFORMATION st1, st2;
01427 HANDLE f1 = 0, f2 = 0;
01428 #endif
01429
01430 rb_secure(2);
01431 #ifdef _WIN32
01432 f1 = w32_io_info(&fname1, &st1);
01433 if (f1 == INVALID_HANDLE_VALUE) return Qfalse;
01434 f2 = w32_io_info(&fname2, &st2);
01435 if (f1) CloseHandle(f1);
01436 if (f2 == INVALID_HANDLE_VALUE) return Qfalse;
01437 if (f2) CloseHandle(f2);
01438
01439 if (st1.dwVolumeSerialNumber == st2.dwVolumeSerialNumber &&
01440 st1.nFileIndexHigh == st2.nFileIndexHigh &&
01441 st1.nFileIndexLow == st2.nFileIndexLow)
01442 return Qtrue;
01443 if (!f1 || !f2) return Qfalse;
01444 if (rb_w32_iswin95()) return Qfalse;
01445 #else
01446 SafeStringValue(fname1);
01447 fname1 = rb_str_new4(fname1);
01448 SafeStringValue(fname2);
01449 if (access(RSTRING(fname1)->ptr, 0)) return Qfalse;
01450 if (access(RSTRING(fname2)->ptr, 0)) return Qfalse;
01451 #endif
01452 fname1 = rb_file_expand_path(fname1, Qnil);
01453 fname2 = rb_file_expand_path(fname2, Qnil);
01454 if (RSTRING(fname1)->len != RSTRING(fname2)->len) return Qfalse;
01455 if (rb_memcicmp(RSTRING(fname1)->ptr, RSTRING(fname2)->ptr, RSTRING(fname1)->len))
01456 return Qfalse;
01457 #endif
01458 return Qtrue;
01459 }
01460
01461
01462
01463
01464
01465
01466
01467
01468 static VALUE
01469 rb_file_s_size(klass, fname)
01470 VALUE klass, fname;
01471 {
01472 struct stat st;
01473
01474 if (rb_stat(fname, &st) < 0)
01475 rb_sys_fail(StringValueCStr(fname));
01476 return OFFT2NUM(st.st_size);
01477 }
01478
01479 static VALUE
01480 rb_file_ftype(st)
01481 struct stat *st;
01482 {
01483 char *t;
01484
01485 if (S_ISREG(st->st_mode)) {
01486 t = "file";
01487 }
01488 else if (S_ISDIR(st->st_mode)) {
01489 t = "directory";
01490 }
01491 else if (S_ISCHR(st->st_mode)) {
01492 t = "characterSpecial";
01493 }
01494 #ifdef S_ISBLK
01495 else if (S_ISBLK(st->st_mode)) {
01496 t = "blockSpecial";
01497 }
01498 #endif
01499 #ifdef S_ISFIFO
01500 else if (S_ISFIFO(st->st_mode)) {
01501 t = "fifo";
01502 }
01503 #endif
01504 #ifdef S_ISLNK
01505 else if (S_ISLNK(st->st_mode)) {
01506 t = "link";
01507 }
01508 #endif
01509 #ifdef S_ISSOCK
01510 else if (S_ISSOCK(st->st_mode)) {
01511 t = "socket";
01512 }
01513 #endif
01514 else {
01515 t = "unknown";
01516 }
01517
01518 return rb_str_new2(t);
01519 }
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536 static VALUE
01537 rb_file_s_ftype(klass, fname)
01538 VALUE klass, fname;
01539 {
01540 struct stat st;
01541
01542 SafeStringValue(fname);
01543 if (lstat(StringValueCStr(fname), &st) == -1) {
01544 rb_sys_fail(RSTRING(fname)->ptr);
01545 }
01546
01547 return rb_file_ftype(&st);
01548 }
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560 static VALUE
01561 rb_file_s_atime(klass, fname)
01562 VALUE klass, fname;
01563 {
01564 struct stat st;
01565
01566 if (rb_stat(fname, &st) < 0)
01567 rb_sys_fail(StringValueCStr(fname));
01568 return rb_time_new(st.st_atime, 0);
01569 }
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582 static VALUE
01583 rb_file_atime(obj)
01584 VALUE obj;
01585 {
01586 OpenFile *fptr;
01587 struct stat st;
01588
01589 GetOpenFile(obj, fptr);
01590 if (fstat(fileno(fptr->f), &st) == -1) {
01591 rb_sys_fail(fptr->path);
01592 }
01593 return rb_time_new(st.st_atime, 0);
01594 }
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606 static VALUE
01607 rb_file_s_mtime(klass, fname)
01608 VALUE klass, fname;
01609 {
01610 struct stat st;
01611
01612 if (rb_stat(fname, &st) < 0)
01613 rb_sys_fail(RSTRING(fname)->ptr);
01614 return rb_time_new(st.st_mtime, 0);
01615 }
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627 static VALUE
01628 rb_file_mtime(obj)
01629 VALUE obj;
01630 {
01631 OpenFile *fptr;
01632 struct stat st;
01633
01634 GetOpenFile(obj, fptr);
01635 if (fstat(fileno(fptr->f), &st) == -1) {
01636 rb_sys_fail(fptr->path);
01637 }
01638 return rb_time_new(st.st_mtime, 0);
01639 }
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653 static VALUE
01654 rb_file_s_ctime(klass, fname)
01655 VALUE klass, fname;
01656 {
01657 struct stat st;
01658
01659 if (rb_stat(fname, &st) < 0)
01660 rb_sys_fail(RSTRING(fname)->ptr);
01661 return rb_time_new(st.st_ctime, 0);
01662 }
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675 static VALUE
01676 rb_file_ctime(obj)
01677 VALUE obj;
01678 {
01679 OpenFile *fptr;
01680 struct stat st;
01681
01682 GetOpenFile(obj, fptr);
01683 if (fstat(fileno(fptr->f), &st) == -1) {
01684 rb_sys_fail(fptr->path);
01685 }
01686 return rb_time_new(st.st_ctime, 0);
01687 }
01688
01689 static void chmod_internal (const char *, void *);
01690 static void
01691 chmod_internal(path, mode)
01692 const char *path;
01693 void *mode;
01694 {
01695 if (chmod(path, (int)mode) < 0)
01696 rb_sys_fail(path);
01697 }
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712 static VALUE
01713 rb_file_s_chmod(argc, argv)
01714 int argc;
01715 VALUE *argv;
01716 {
01717 VALUE vmode;
01718 VALUE rest;
01719 int mode;
01720 long n;
01721
01722 rb_secure(2);
01723 rb_scan_args(argc, argv, "1*", &vmode, &rest);
01724 mode = NUM2INT(vmode);
01725
01726 n = apply2files(chmod_internal, rest, (void *)(long)mode);
01727 return LONG2FIX(n);
01728 }
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743 static VALUE
01744 rb_file_chmod(obj, vmode)
01745 VALUE obj, vmode;
01746 {
01747 OpenFile *fptr;
01748 int mode;
01749
01750 rb_secure(2);
01751 mode = NUM2INT(vmode);
01752
01753 GetOpenFile(obj, fptr);
01754 #ifdef HAVE_FCHMOD
01755 if (fchmod(fileno(fptr->f), mode) == -1)
01756 rb_sys_fail(fptr->path);
01757 #else
01758 if (!fptr->path) return Qnil;
01759 if (chmod(fptr->path, mode) == -1)
01760 rb_sys_fail(fptr->path);
01761 #endif
01762
01763 return INT2FIX(0);
01764 }
01765
01766 #if defined(HAVE_LCHMOD)
01767 static void lchmod_internal (const char *, void *);
01768 static void
01769 lchmod_internal(path, mode)
01770 const char *path;
01771 void *mode;
01772 {
01773 if (lchmod(path, (int)mode) < 0)
01774 rb_sys_fail(path);
0