/[rdesktop]/sourceforge.net/trunk/rdesktop/disk.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/disk.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 747 by astrand, Mon Aug 9 13:50:41 2004 UTC revision 795 by stargo, Wed Nov 3 13:56:52 2004 UTC
# Line 31  Line 31 
31  #include <utime.h>  #include <utime.h>
32  #include <time.h>               /* ctime */  #include <time.h>               /* ctime */
33    
34  #if defined(HAVE_DIRFD)  #if (defined(HAVE_DIRFD) || (HAVE_DECL_DIRFD == 1))
35  #define DIRFD(a) (dirfd(a))  #define DIRFD(a) (dirfd(a))
36  #else  #else
37  #define DIRFD(a) ((a)->DIR_FD_MEMBER_NAME)  #define DIRFD(a) ((a)->DIR_FD_MEMBER_NAME)
# Line 52  Line 52 
52  #define STATFS_T statvfs  #define STATFS_T statvfs
53  #define F_NAMELEN(buf) ((buf).f_namemax)  #define F_NAMELEN(buf) ((buf).f_namemax)
54    
55  #elif (defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__))  #elif (defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__APPLE__))
56  #include <sys/param.h>  #include <sys/param.h>
57  #include <sys/mount.h>  #include <sys/mount.h>
58  #define STATFS_FN(path, buf) (statfs(path,buf))  #define STATFS_FN(path, buf) (statfs(path,buf))
# Line 81  Line 81 
81  extern RDPDR_DEVICE g_rdpdr_device[];  extern RDPDR_DEVICE g_rdpdr_device[];
82    
83  FILEINFO g_fileinfo[MAX_OPEN_FILES];  FILEINFO g_fileinfo[MAX_OPEN_FILES];
84    BOOL g_notify_stamp = False;
85    
86  typedef struct  typedef struct
87  {  {
# Line 90  typedef struct Line 91  typedef struct
91          char type[256];          char type[256];
92  } FsInfoType;  } FsInfoType;
93    
94    static NTSTATUS NotifyInfo(NTHANDLE handle, uint32 info_class, NOTIFY * p);
95    
96  static time_t  static time_t
97  get_create_time(struct stat *st)  get_create_time(struct stat *st)
# Line 132  convert_1970_to_filetime(uint32 high, ui Line 134  convert_1970_to_filetime(uint32 high, ui
134    
135  }  }
136    
137    /* A wrapper for ftruncate which supports growing files, even if the
138       native ftruncate doesn't. This is needed on Linux FAT filesystems,
139       for example. */
140    static int
141    ftruncate_growable(int fd, off_t length)
142    {
143            int ret;
144            off_t pos;
145            static const char zero;
146    
147            /* Try the simple method first */
148            if ((ret = ftruncate(fd, length)) != -1)
149            {
150                    return ret;
151            }
152    
153            /*
154             * Some kind of error. Perhaps we were trying to grow. Retry
155             * in a safe way.
156             */
157    
158            /* Get current position */
159            if ((pos = lseek(fd, 0, SEEK_CUR)) == -1)
160            {
161                    perror("lseek");
162                    return -1;
163            }
164    
165            /* Seek to new size */
166            if (lseek(fd, length, SEEK_SET) == -1)
167            {
168                    perror("lseek");
169                    return -1;
170            }
171    
172            /* Write a zero */
173            if (write(fd, &zero, 1) == -1)
174            {
175                    perror("write");
176                    return -1;
177            }
178    
179            /* Truncate. This shouldn't fail. */
180            if (ftruncate(fd, length) == -1)
181            {
182                    perror("ftruncate");
183                    return -1;
184            }
185    
186            /* Restore position */
187            if (lseek(fd, pos, SEEK_SET) == -1)
188            {
189                    perror("lseek");
190                    return -1;
191            }
192    
193            return 0;
194    }
195    
196    /* Just like open(2), but if a open with O_EXCL fails, retry with
197       GUARDED semantics. This might be necessary because some filesystems
198       (such as NFS filesystems mounted from a unfsd server) doesn't
199       support O_EXCL. GUARDED semantics are subject to race conditions,
200       but we can live with that.
201    */
202    static int
203    open_weak_exclusive(const char *pathname, int flags, mode_t mode)
204    {
205            int ret;
206            struct stat statbuf;
207    
208            ret = open(pathname, flags, mode);
209            if (ret != -1 || !(flags & O_EXCL))
210            {
211                    /* Success, or not using O_EXCL */
212                    return ret;
213            }
214    
215            /* An error occured, and we are using O_EXCL. In case the FS
216               doesn't support O_EXCL, some kind of error will be
217               returned. Unfortunately, we don't know which one. Linux
218               2.6.8 seems to return 524, but I cannot find a documented
219               #define for this case. So, we'll return only on errors that
220               we know aren't related to O_EXCL. */
221            switch (errno)
222            {
223                    case EACCES:
224                    case EEXIST:
225                    case EINTR:
226                    case EISDIR:
227                    case ELOOP:
228                    case ENAMETOOLONG:
229                    case ENOENT:
230                    case ENOTDIR:
231                            return ret;
232            }
233    
234            /* Retry with GUARDED semantics */
235            if (stat(pathname, &statbuf) != -1)
236            {
237                    /* File exists */
238                    errno = EEXIST;
239                    return -1;
240            }
241            else
242            {
243                    return open(pathname, flags & ~O_EXCL, mode);
244            }
245    }
246    
247  /* Enumeration of devices from rdesktop.c        */  /* Enumeration of devices from rdesktop.c        */
248  /* returns numer of units found and initialized. */  /* returns numer of units found and initialized. */
# Line 169  disk_enum_devices(uint32 * id, char *opt Line 280  disk_enum_devices(uint32 * id, char *opt
280  /* Opens or creates a file or directory */  /* Opens or creates a file or directory */
281  static NTSTATUS  static NTSTATUS
282  disk_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition,  disk_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition,
283              uint32 flags_and_attributes, char *filename, HANDLE * phandle)              uint32 flags_and_attributes, char *filename, NTHANDLE * phandle)
284  {  {
285          HANDLE handle;          NTHANDLE handle;
286          DIR *dirp;          DIR *dirp;
287          int flags, mode;          int flags, mode;
288          char path[256];          char path[256];
# Line 182  disk_create(uint32 device_id, uint32 acc Line 293  disk_create(uint32 device_id, uint32 acc
293          flags = 0;          flags = 0;
294          mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;          mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
295    
296            if (*filename && filename[strlen(filename) - 1] == '/')
         if (filename[strlen(filename) - 1] == '/')  
297                  filename[strlen(filename) - 1] = 0;                  filename[strlen(filename) - 1] = 0;
298          sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename);          sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename);
299    
# Line 220  disk_create(uint32 device_id, uint32 acc Line 330  disk_create(uint32 device_id, uint32 acc
330                          break;                          break;
331          }          }
332    
333          //printf("Open: \"%s\"  flags: %u, accessmask: %u sharemode: %u create disp: %u\n", path, flags_and_attributes, accessmask, sharemode, create_disposition);          //printf("Open: \"%s\"  flags: %X, accessmask: %X sharemode: %X create disp: %X\n", path, flags_and_attributes, accessmask, sharemode, create_disposition);
334    
335          // Get information about file and set that flag ourselfs          // Get information about file and set that flag ourselfs
336          if ((stat(path, &filestat) == 0) && (S_ISDIR(filestat.st_mode)))          if ((stat(path, &filestat) == 0) && (S_ISDIR(filestat.st_mode)))
# Line 276  disk_create(uint32 device_id, uint32 acc Line 386  disk_create(uint32 device_id, uint32 acc
386                          flags |= O_RDONLY;                          flags |= O_RDONLY;
387                  }                  }
388    
389                  handle = open(path, flags, mode);                  handle = open_weak_exclusive(path, flags, mode);
390                  if (handle == -1)                  if (handle == -1)
391                  {                  {
392                          switch (errno)                          switch (errno)
# Line 316  disk_create(uint32 device_id, uint32 acc Line 426  disk_create(uint32 device_id, uint32 acc
426    
427          if (dirp)          if (dirp)
428                  g_fileinfo[handle].pdir = dirp;                  g_fileinfo[handle].pdir = dirp;
429            else
430                    g_fileinfo[handle].pdir = NULL;
431    
432          g_fileinfo[handle].device_id = device_id;          g_fileinfo[handle].device_id = device_id;
433          g_fileinfo[handle].flags_and_attributes = flags_and_attributes;          g_fileinfo[handle].flags_and_attributes = flags_and_attributes;
434            g_fileinfo[handle].accessmask = accessmask;
435          strncpy(g_fileinfo[handle].path, path, 255);          strncpy(g_fileinfo[handle].path, path, 255);
436            g_fileinfo[handle].delete_on_close = False;
437            g_notify_stamp = True;
438    
439          *phandle = handle;          *phandle = handle;
440          return STATUS_SUCCESS;          return STATUS_SUCCESS;
441  }  }
442    
443  static NTSTATUS  static NTSTATUS
444  disk_close(HANDLE handle)  disk_close(NTHANDLE handle)
445  {  {
446          struct fileinfo *pfinfo;          struct fileinfo *pfinfo;
447    
448          pfinfo = &(g_fileinfo[handle]);          pfinfo = &(g_fileinfo[handle]);
449    
450          if (pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE)          g_notify_stamp = True;
451    
452            rdpdr_abort_io(handle, 0, STATUS_CANCELLED);
453    
454            if (pfinfo->pdir)
455          {          {
456                  closedir(pfinfo->pdir);                  if (closedir(pfinfo->pdir) < 0)
457                  //FIXME: Should check exit code                  {
458                            perror("closedir");
459                            return STATUS_INVALID_HANDLE;
460                    }
461    
462                    if (pfinfo->delete_on_close)
463                            if (rmdir(pfinfo->path) < 0)
464                            {
465                                    perror(pfinfo->path);
466                                    return STATUS_ACCESS_DENIED;
467                            }
468                    pfinfo->delete_on_close = False;
469          }          }
470          else          else
471          {          {
472                  close(handle);                  if (close(handle) < 0)
473                    {
474                            perror("close");
475                            return STATUS_INVALID_HANDLE;
476                    }
477                    if (pfinfo->delete_on_close)
478                            if (unlink(pfinfo->path) < 0)
479                            {
480                                    perror(pfinfo->path);
481                                    return STATUS_ACCESS_DENIED;
482                            }
483    
484                    pfinfo->delete_on_close = False;
485          }          }
486    
487          return STATUS_SUCCESS;          return STATUS_SUCCESS;
488  }  }
489    
490  static NTSTATUS  static NTSTATUS
491  disk_read(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)  disk_read(NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
492  {  {
493          int n;          int n;
494    
# Line 369  disk_read(HANDLE handle, uint8 * data, u Line 512  disk_read(HANDLE handle, uint8 * data, u
512                  switch (errno)                  switch (errno)
513                  {                  {
514                          case EISDIR:                          case EISDIR:
515                                  return STATUS_FILE_IS_A_DIRECTORY;                                  /* Implement 24 Byte directory read ??
516                                       with STATUS_NOT_IMPLEMENTED server doesn't read again */
517                                    /* return STATUS_FILE_IS_A_DIRECTORY; */
518                                    return STATUS_NOT_IMPLEMENTED;
519                          default:                          default:
520                                  perror("read");                                  perror("read");
521                                  return STATUS_INVALID_PARAMETER;                                  return STATUS_INVALID_PARAMETER;
# Line 382  disk_read(HANDLE handle, uint8 * data, u Line 528  disk_read(HANDLE handle, uint8 * data, u
528  }  }
529    
530  static NTSTATUS  static NTSTATUS
531  disk_write(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)  disk_write(NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
532  {  {
533          int n;          int n;
534    
# Line 409  disk_write(HANDLE handle, uint8 * data, Line 555  disk_write(HANDLE handle, uint8 * data,
555  }  }
556    
557  NTSTATUS  NTSTATUS
558  disk_query_information(HANDLE handle, uint32 info_class, STREAM out)  disk_query_information(NTHANDLE handle, uint32 info_class, STREAM out)
559  {  {
560          uint32 file_attributes, ft_high, ft_low;          uint32 file_attributes, ft_high, ft_low;
561          struct stat filestat;          struct stat filestat;
# Line 490  disk_query_information(HANDLE handle, ui Line 636  disk_query_information(HANDLE handle, ui
636  }  }
637    
638  NTSTATUS  NTSTATUS
639  disk_set_information(HANDLE handle, uint32 info_class, STREAM in, STREAM out)  disk_set_information(NTHANDLE handle, uint32 info_class, STREAM in, STREAM out)
640  {  {
641          uint32 device_id, length, file_attributes, ft_high, ft_low;          uint32 length, file_attributes, ft_high, ft_low, delete_on_close;
642          char newname[256], fullpath[256];          char newname[256], fullpath[256];
643          struct fileinfo *pfinfo;          struct fileinfo *pfinfo;
   
644          int mode;          int mode;
645          struct stat filestat;          struct stat filestat;
646          time_t write_time, change_time, access_time, mod_time;          time_t write_time, change_time, access_time, mod_time;
# Line 503  disk_set_information(HANDLE handle, uint Line 648  disk_set_information(HANDLE handle, uint
648          struct STATFS_T stat_fs;          struct STATFS_T stat_fs;
649    
650          pfinfo = &(g_fileinfo[handle]);          pfinfo = &(g_fileinfo[handle]);
651            g_notify_stamp = True;
652    
653          switch (info_class)          switch (info_class)
654          {          {
# Line 562  disk_set_information(HANDLE handle, uint Line 708  disk_set_information(HANDLE handle, uint
708                                  printf("FileBasicInformation modification time %s",                                  printf("FileBasicInformation modification time %s",
709                                         ctime(&tvs.modtime));                                         ctime(&tvs.modtime));
710  #endif  #endif
711                                  if (utime(pfinfo->path, &tvs))                                  if (utime(pfinfo->path, &tvs) && errno != EPERM)
712                                          return STATUS_ACCESS_DENIED;                                          return STATUS_ACCESS_DENIED;
713                          }                          }
714    
# Line 620  disk_set_information(HANDLE handle, uint Line 766  disk_set_information(HANDLE handle, uint
766                             FileDispositionInformation requests with                             FileDispositionInformation requests with
767                             DeleteFile set to FALSE should unschedule                             DeleteFile set to FALSE should unschedule
768                             the delete. See                             the delete. See
769                             http://www.osronline.com/article.cfm?article=245. Currently,                             http://www.osronline.com/article.cfm?article=245. */
                            we are deleting the file immediately. I  
                            guess this is a FIXME. */  
770    
771                          //in_uint32_le(in, delete_on_close);                          in_uint32_le(in, delete_on_close);
772    
773                          /* Make sure we close the file before                          if (delete_on_close ||
774                             unlinking it. Not doing so would trigger                              (pfinfo->
775                             silly-delete if using NFS, which might fail                               accessmask & (FILE_DELETE_ON_CLOSE | FILE_COMPLETE_IF_OPLOCKED)))
                            on FAT floppies, for example. */  
                         disk_close(handle);  
   
                         if ((pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE))       // remove a directory  
776                          {                          {
777                                  if (rmdir(pfinfo->path) < 0)                                  pfinfo->delete_on_close = True;
                                         return STATUS_ACCESS_DENIED;  
778                          }                          }
                         else if (unlink(pfinfo->path) < 0)      // unlink a file  
                                 return STATUS_ACCESS_DENIED;  
779    
780                          break;                          break;
781    
# Line 655  disk_set_information(HANDLE handle, uint Line 792  disk_set_information(HANDLE handle, uint
792    
793                          /* prevents start of writing if not enough space left on device */                          /* prevents start of writing if not enough space left on device */
794                          if (STATFS_FN(g_rdpdr_device[pfinfo->device_id].local_path, &stat_fs) == 0)                          if (STATFS_FN(g_rdpdr_device[pfinfo->device_id].local_path, &stat_fs) == 0)
795                                  if (stat_fs.f_bsize * stat_fs.f_bfree < length)                                  if (stat_fs.f_bfree * stat_fs.f_bsize < length)
796                                          return STATUS_DISK_FULL;                                          return STATUS_DISK_FULL;
797    
798                          /* FIXME: Growing file with ftruncate doesn't                          if (ftruncate_growable(handle, length) != 0)
                            work with Linux FAT fs */  
                         if (ftruncate(handle, length) != 0)  
799                          {                          {
                                 perror("ftruncate");  
800                                  return STATUS_DISK_FULL;                                  return STATUS_DISK_FULL;
801                          }                          }
802    
# Line 675  disk_set_information(HANDLE handle, uint Line 809  disk_set_information(HANDLE handle, uint
809          return STATUS_SUCCESS;          return STATUS_SUCCESS;
810  }  }
811    
812    NTSTATUS
813    disk_check_notify(NTHANDLE handle)
814    {
815            struct fileinfo *pfinfo;
816            NTSTATUS status = STATUS_PENDING;
817    
818            NOTIFY notify;
819    
820            pfinfo = &(g_fileinfo[handle]);
821            if (!pfinfo->pdir)
822                    return STATUS_INVALID_DEVICE_REQUEST;
823    
824    
825    
826            status = NotifyInfo(handle, pfinfo->info_class, &notify);
827    
828            if (status != STATUS_PENDING)
829                    return status;
830    
831            if (memcmp(&pfinfo->notify, &notify, sizeof(NOTIFY)))
832            {
833                    //printf("disk_check_notify found changed event\n");
834                    memcpy(&pfinfo->notify, &notify, sizeof(NOTIFY));
835                    status = STATUS_NOTIFY_ENUM_DIR;
836            }
837    
838            return status;
839    
840    
841    }
842    
843    NTSTATUS
844    disk_create_notify(NTHANDLE handle, uint32 info_class)
845    {
846    
847            struct fileinfo *pfinfo;
848            NTSTATUS ret = STATUS_PENDING;
849    
850            /* printf("start disk_create_notify info_class %X\n", info_class); */
851    
852            pfinfo = &(g_fileinfo[handle]);
853            pfinfo->info_class = info_class;
854    
855            ret = NotifyInfo(handle, info_class, &pfinfo->notify);
856    
857            if (info_class & 0x1000)
858            {                       /* ???? */
859                    if (ret == STATUS_PENDING)
860                            return STATUS_SUCCESS;
861            }
862    
863            /* printf("disk_create_notify: num_entries %d\n", pfinfo->notify.num_entries); */
864    
865    
866            return ret;
867    
868    }
869    
870    static NTSTATUS
871    NotifyInfo(NTHANDLE handle, uint32 info_class, NOTIFY * p)
872    {
873            struct fileinfo *pfinfo;
874            struct stat buf;
875            struct dirent *dp;
876            char *fullname;
877            DIR *dpr;
878    
879            pfinfo = &(g_fileinfo[handle]);
880            if (fstat(handle, &buf) < 0)
881            {
882                    perror("NotifyInfo");
883                    return STATUS_ACCESS_DENIED;
884            }
885            p->modify_time = buf.st_mtime;
886            p->status_time = buf.st_ctime;
887            p->num_entries = 0;
888            p->total_time = 0;
889    
890    
891            dpr = opendir(pfinfo->path);
892            if (!dpr)
893            {
894                    perror("NotifyInfo");
895                    return STATUS_ACCESS_DENIED;
896            }
897    
898    
899            while ((dp = readdir(dpr)))
900            {
901                    if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
902                            continue;
903                    p->num_entries++;
904                    fullname = xmalloc(strlen(pfinfo->path) + strlen(dp->d_name) + 2);
905                    sprintf(fullname, "%s/%s", pfinfo->path, dp->d_name);
906    
907                    if (!stat(fullname, &buf))
908                    {
909                            p->total_time += (buf.st_mtime + buf.st_ctime);
910                    }
911    
912                    xfree(fullname);
913            }
914            closedir(dpr);
915    
916            return STATUS_PENDING;
917    }
918    
919  static FsInfoType *  static FsInfoType *
920  FsVolumeInfo(char *fpath)  FsVolumeInfo(char *fpath)
921  {  {
922    
 #ifdef HAVE_MNTENT_H  
923          FILE *fdfs;          FILE *fdfs;
         struct mntent *e;  
924          static FsInfoType info;          static FsInfoType info;
925    #ifdef HAVE_MNTENT_H
926            struct mntent *e;
927    #endif
928    
929          /* initialize */          /* initialize */
930          memset(&info, 0, sizeof(info));          memset(&info, 0, sizeof(info));
931          strcpy(info.label, "RDESKTOP");          strcpy(info.label, "RDESKTOP");
932          strcpy(info.type, "RDPFS");          strcpy(info.type, "RDPFS");
933    
934    #ifdef HAVE_MNTENT_H
935          fdfs = setmntent(MNTENT_PATH, "r");          fdfs = setmntent(MNTENT_PATH, "r");
936          if (!fdfs)          if (!fdfs)
937                  return &info;                  return &info;
# Line 731  FsVolumeInfo(char *fpath) Line 974  FsVolumeInfo(char *fpath)
974          }          }
975          endmntent(fdfs);          endmntent(fdfs);
976  #else  #else
         static FsInfoType info;  
   
977          /* initialize */          /* initialize */
978          memset(&info, 0, sizeof(info));          memset(&info, 0, sizeof(info));
979          strcpy(info.label, "RDESKTOP");          strcpy(info.label, "RDESKTOP");
# Line 744  FsVolumeInfo(char *fpath) Line 985  FsVolumeInfo(char *fpath)
985    
986    
987  NTSTATUS  NTSTATUS
988  disk_query_volume_information(HANDLE handle, uint32 info_class, STREAM out)  disk_query_volume_information(NTHANDLE handle, uint32 info_class, STREAM out)
989  {  {
990          struct STATFS_T stat_fs;          struct STATFS_T stat_fs;
991          struct fileinfo *pfinfo;          struct fileinfo *pfinfo;
# Line 809  disk_query_volume_information(HANDLE han Line 1050  disk_query_volume_information(HANDLE han
1050  }  }
1051    
1052  NTSTATUS  NTSTATUS
1053  disk_query_directory(HANDLE handle, uint32 info_class, char *pattern, STREAM out)  disk_query_directory(NTHANDLE handle, uint32 info_class, char *pattern, STREAM out)
1054  {  {
1055          uint32 file_attributes, ft_low, ft_high;          uint32 file_attributes, ft_low, ft_high;
1056          char *dirname, fullpath[256];          char *dirname, fullpath[256];
# Line 919  disk_query_directory(HANDLE handle, uint Line 1160  disk_query_directory(HANDLE handle, uint
1160    
1161    
1162  static NTSTATUS  static NTSTATUS
1163  disk_device_control(HANDLE handle, uint32 request, STREAM in, STREAM out)  disk_device_control(NTHANDLE handle, uint32 request, STREAM in, STREAM out)
1164  {  {
         uint32 result;  
   
1165          if (((request >> 16) != 20) || ((request >> 16) != 9))          if (((request >> 16) != 20) || ((request >> 16) != 9))
1166                  return STATUS_INVALID_PARAMETER;                  return STATUS_INVALID_PARAMETER;
1167    

Legend:
Removed from v.747  
changed lines
  Added in v.795

  ViewVC Help
Powered by ViewVC 1.1.26