/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/disk.c

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

revision 785 by astrand, Thu Oct 21 08:10:04 2004 UTC revision 827 by astrand, Thu Mar 3 08:48:24 2005 UTC
# Line 18  Line 18 
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
21    #include "rdesktop.h"
22  #include "disk.h"  #include "disk.h"
23    
24  #include <sys/types.h>  #include <sys/types.h>
# Line 66  Line 67 
67  #define STATFS_T statvfs  #define STATFS_T statvfs
68  #define F_NAMELEN(buf) ((buf).f_namemax)  #define F_NAMELEN(buf) ((buf).f_namemax)
69    
70    #elif (defined(__alpha) && !defined(linux))
71    #include <sys/mount.h>          /* osf1 statfs */
72    #define STATFS_FN(path, buf) (statfs(path,buf,sizeof(buf)))
73    #define STATFS_T statfs
74    #define F_NAMELEN(buf) (255)
75    
76  #else  #else
77  #include <sys/vfs.h>            /* linux statfs */  #include <sys/vfs.h>            /* linux statfs */
78  #include <mntent.h>  #include <mntent.h>
# Line 76  Line 83 
83  #define F_NAMELEN(buf) ((buf).f_namelen)  #define F_NAMELEN(buf) ((buf).f_namelen)
84  #endif  #endif
85    
 #include "rdesktop.h"  
   
86  extern RDPDR_DEVICE g_rdpdr_device[];  extern RDPDR_DEVICE g_rdpdr_device[];
87    
88  FILEINFO g_fileinfo[MAX_OPEN_FILES];  FILEINFO g_fileinfo[MAX_OPEN_FILES];
89    BOOL g_notify_stamp = False;
90    
91  typedef struct  typedef struct
92  {  {
# Line 90  typedef struct Line 96  typedef struct
96          char type[256];          char type[256];
97  } FsInfoType;  } FsInfoType;
98    
99    static NTSTATUS NotifyInfo(NTHANDLE handle, uint32 info_class, NOTIFY * p);
100    
101  static time_t  static time_t
102  get_create_time(struct stat *st)  get_create_time(struct stat *st)
# Line 191  ftruncate_growable(int fd, off_t length) Line 198  ftruncate_growable(int fd, off_t length)
198          return 0;          return 0;
199  }  }
200    
201    /* Just like open(2), but if a open with O_EXCL fails, retry with
202       GUARDED semantics. This might be necessary because some filesystems
203       (such as NFS filesystems mounted from a unfsd server) doesn't
204       support O_EXCL. GUARDED semantics are subject to race conditions,
205       but we can live with that.
206    */
207    static int
208    open_weak_exclusive(const char *pathname, int flags, mode_t mode)
209    {
210            int ret;
211            struct stat statbuf;
212    
213            ret = open(pathname, flags, mode);
214            if (ret != -1 || !(flags & O_EXCL))
215            {
216                    /* Success, or not using O_EXCL */
217                    return ret;
218            }
219    
220            /* An error occured, and we are using O_EXCL. In case the FS
221               doesn't support O_EXCL, some kind of error will be
222               returned. Unfortunately, we don't know which one. Linux
223               2.6.8 seems to return 524, but I cannot find a documented
224               #define for this case. So, we'll return only on errors that
225               we know aren't related to O_EXCL. */
226            switch (errno)
227            {
228                    case EACCES:
229                    case EEXIST:
230                    case EINTR:
231                    case EISDIR:
232                    case ELOOP:
233                    case ENAMETOOLONG:
234                    case ENOENT:
235                    case ENOTDIR:
236                            return ret;
237            }
238    
239            /* Retry with GUARDED semantics */
240            if (stat(pathname, &statbuf) != -1)
241            {
242                    /* File exists */
243                    errno = EEXIST;
244                    return -1;
245            }
246            else
247            {
248                    return open(pathname, flags & ~O_EXCL, mode);
249            }
250    }
251    
252  /* Enumeration of devices from rdesktop.c        */  /* Enumeration of devices from rdesktop.c        */
253  /* returns numer of units found and initialized. */  /* returns numer of units found and initialized. */
# Line 209  disk_enum_devices(uint32 * id, char *opt Line 266  disk_enum_devices(uint32 * id, char *opt
266          {          {
267                  pos2 = next_arg(optarg, '=');                  pos2 = next_arg(optarg, '=');
268    
269                  strncpy(g_rdpdr_device[*id].name, optarg, sizeof(g_rdpdr_device[*id].name));                  strncpy(g_rdpdr_device[*id].name, optarg, sizeof(g_rdpdr_device[*id].name) - 1);
270                  if (strlen(optarg) > 8)                  if (strlen(optarg) > (sizeof(g_rdpdr_device[*id].name) - 1))
271                          fprintf(stderr, "share name %s truncated to %s\n", optarg,                          fprintf(stderr, "share name %s truncated to %s\n", optarg,
272                                  g_rdpdr_device[*id].name);                                  g_rdpdr_device[*id].name);
273    
# Line 241  disk_create(uint32 device_id, uint32 acc Line 298  disk_create(uint32 device_id, uint32 acc
298          flags = 0;          flags = 0;
299          mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;          mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
300    
301            if (*filename && filename[strlen(filename) - 1] == '/')
         if (filename[strlen(filename) - 1] == '/')  
302                  filename[strlen(filename) - 1] = 0;                  filename[strlen(filename) - 1] = 0;
303          sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename);          sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename);
304    
# Line 279  disk_create(uint32 device_id, uint32 acc Line 335  disk_create(uint32 device_id, uint32 acc
335                          break;                          break;
336          }          }
337    
338          //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);
339    
340          // Get information about file and set that flag ourselfs          // Get information about file and set that flag ourselfs
341          if ((stat(path, &filestat) == 0) && (S_ISDIR(filestat.st_mode)))          if ((stat(path, &filestat) == 0) && (S_ISDIR(filestat.st_mode)))
# Line 335  disk_create(uint32 device_id, uint32 acc Line 391  disk_create(uint32 device_id, uint32 acc
391                          flags |= O_RDONLY;                          flags |= O_RDONLY;
392                  }                  }
393    
394                  handle = open(path, flags, mode);                  handle = open_weak_exclusive(path, flags, mode);
395                  if (handle == -1)                  if (handle == -1)
396                  {                  {
397                          switch (errno)                          switch (errno)
# Line 375  disk_create(uint32 device_id, uint32 acc Line 431  disk_create(uint32 device_id, uint32 acc
431    
432          if (dirp)          if (dirp)
433                  g_fileinfo[handle].pdir = dirp;                  g_fileinfo[handle].pdir = dirp;
434            else
435                    g_fileinfo[handle].pdir = NULL;
436    
437          g_fileinfo[handle].device_id = device_id;          g_fileinfo[handle].device_id = device_id;
438          g_fileinfo[handle].flags_and_attributes = flags_and_attributes;          g_fileinfo[handle].flags_and_attributes = flags_and_attributes;
439            g_fileinfo[handle].accessmask = accessmask;
440          strncpy(g_fileinfo[handle].path, path, 255);          strncpy(g_fileinfo[handle].path, path, 255);
441            g_fileinfo[handle].delete_on_close = False;
442            g_notify_stamp = True;
443    
444          *phandle = handle;          *phandle = handle;
445          return STATUS_SUCCESS;          return STATUS_SUCCESS;
# Line 390  disk_close(NTHANDLE handle) Line 452  disk_close(NTHANDLE handle)
452    
453          pfinfo = &(g_fileinfo[handle]);          pfinfo = &(g_fileinfo[handle]);
454    
455          if (pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE)          g_notify_stamp = True;
456    
457            rdpdr_abort_io(handle, 0, STATUS_CANCELLED);
458    
459            if (pfinfo->pdir)
460          {          {
461                  closedir(pfinfo->pdir);                  if (closedir(pfinfo->pdir) < 0)
462                  //FIXME: Should check exit code                  {
463                            perror("closedir");
464                            return STATUS_INVALID_HANDLE;
465                    }
466    
467                    if (pfinfo->delete_on_close)
468                            if (rmdir(pfinfo->path) < 0)
469                            {
470                                    perror(pfinfo->path);
471                                    return STATUS_ACCESS_DENIED;
472                            }
473                    pfinfo->delete_on_close = False;
474          }          }
475          else          else
476          {          {
477                  close(handle);                  if (close(handle) < 0)
478                    {
479                            perror("close");
480                            return STATUS_INVALID_HANDLE;
481                    }
482                    if (pfinfo->delete_on_close)
483                            if (unlink(pfinfo->path) < 0)
484                            {
485                                    perror(pfinfo->path);
486                                    return STATUS_ACCESS_DENIED;
487                            }
488    
489                    pfinfo->delete_on_close = False;
490          }          }
491    
492          return STATUS_SUCCESS;          return STATUS_SUCCESS;
# Line 428  disk_read(NTHANDLE handle, uint8 * data, Line 517  disk_read(NTHANDLE handle, uint8 * data,
517                  switch (errno)                  switch (errno)
518                  {                  {
519                          case EISDIR:                          case EISDIR:
520                                  return STATUS_FILE_IS_A_DIRECTORY;                                  /* Implement 24 Byte directory read ??
521                                       with STATUS_NOT_IMPLEMENTED server doesn't read again */
522                                    /* return STATUS_FILE_IS_A_DIRECTORY; */
523                                    return STATUS_NOT_IMPLEMENTED;
524                          default:                          default:
525                                  perror("read");                                  perror("read");
526                                  return STATUS_INVALID_PARAMETER;                                  return STATUS_INVALID_PARAMETER;
# Line 551  disk_query_information(NTHANDLE handle, Line 643  disk_query_information(NTHANDLE handle,
643  NTSTATUS  NTSTATUS
644  disk_set_information(NTHANDLE handle, uint32 info_class, STREAM in, STREAM out)  disk_set_information(NTHANDLE handle, uint32 info_class, STREAM in, STREAM out)
645  {  {
646          uint32 device_id, length, file_attributes, ft_high, ft_low;          uint32 length, file_attributes, ft_high, ft_low, delete_on_close;
647          char newname[256], fullpath[256];          char newname[256], fullpath[256];
648          struct fileinfo *pfinfo;          struct fileinfo *pfinfo;
   
649          int mode;          int mode;
650          struct stat filestat;          struct stat filestat;
651          time_t write_time, change_time, access_time, mod_time;          time_t write_time, change_time, access_time, mod_time;
# Line 562  disk_set_information(NTHANDLE handle, ui Line 653  disk_set_information(NTHANDLE handle, ui
653          struct STATFS_T stat_fs;          struct STATFS_T stat_fs;
654    
655          pfinfo = &(g_fileinfo[handle]);          pfinfo = &(g_fileinfo[handle]);
656            g_notify_stamp = True;
657    
658          switch (info_class)          switch (info_class)
659          {          {
# Line 621  disk_set_information(NTHANDLE handle, ui Line 713  disk_set_information(NTHANDLE handle, ui
713                                  printf("FileBasicInformation modification time %s",                                  printf("FileBasicInformation modification time %s",
714                                         ctime(&tvs.modtime));                                         ctime(&tvs.modtime));
715  #endif  #endif
716                                  if (utime(pfinfo->path, &tvs))                                  if (utime(pfinfo->path, &tvs) && errno != EPERM)
717                                          return STATUS_ACCESS_DENIED;                                          return STATUS_ACCESS_DENIED;
718                          }                          }
719    
# Line 679  disk_set_information(NTHANDLE handle, ui Line 771  disk_set_information(NTHANDLE handle, ui
771                             FileDispositionInformation requests with                             FileDispositionInformation requests with
772                             DeleteFile set to FALSE should unschedule                             DeleteFile set to FALSE should unschedule
773                             the delete. See                             the delete. See
774                             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. */  
   
                         //in_uint32_le(in, delete_on_close);  
775    
776                          /* Make sure we close the file before                          in_uint32_le(in, delete_on_close);
                            unlinking it. Not doing so would trigger  
                            silly-delete if using NFS, which might fail  
                            on FAT floppies, for example. */  
                         disk_close(handle);  
777    
778                          if ((pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE))       // remove a directory                          if (delete_on_close ||
779                                (pfinfo->
780                                 accessmask & (FILE_DELETE_ON_CLOSE | FILE_COMPLETE_IF_OPLOCKED)))
781                          {                          {
782                                  if (rmdir(pfinfo->path) < 0)                                  pfinfo->delete_on_close = True;
                                         return STATUS_ACCESS_DENIED;  
783                          }                          }
                         else if (unlink(pfinfo->path) < 0)      // unlink a file  
                                 return STATUS_ACCESS_DENIED;  
784    
785                          break;                          break;
786    
# Line 714  disk_set_information(NTHANDLE handle, ui Line 797  disk_set_information(NTHANDLE handle, ui
797    
798                          /* prevents start of writing if not enough space left on device */                          /* prevents start of writing if not enough space left on device */
799                          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)
800                                  if (stat_fs.f_bsize * stat_fs.f_bfree < length)                                  if (stat_fs.f_bfree * stat_fs.f_bsize < length)
801                                          return STATUS_DISK_FULL;                                          return STATUS_DISK_FULL;
802    
803                          if (ftruncate_growable(handle, length) != 0)                          if (ftruncate_growable(handle, length) != 0)
# Line 731  disk_set_information(NTHANDLE handle, ui Line 814  disk_set_information(NTHANDLE handle, ui
814          return STATUS_SUCCESS;          return STATUS_SUCCESS;
815  }  }
816    
817    NTSTATUS
818    disk_check_notify(NTHANDLE handle)
819    {
820            struct fileinfo *pfinfo;
821            NTSTATUS status = STATUS_PENDING;
822    
823            NOTIFY notify;
824    
825            pfinfo = &(g_fileinfo[handle]);
826            if (!pfinfo->pdir)
827                    return STATUS_INVALID_DEVICE_REQUEST;
828    
829    
830    
831            status = NotifyInfo(handle, pfinfo->info_class, &notify);
832    
833            if (status != STATUS_PENDING)
834                    return status;
835    
836            if (memcmp(&pfinfo->notify, &notify, sizeof(NOTIFY)))
837            {
838                    //printf("disk_check_notify found changed event\n");
839                    memcpy(&pfinfo->notify, &notify, sizeof(NOTIFY));
840                    status = STATUS_NOTIFY_ENUM_DIR;
841            }
842    
843            return status;
844    
845    
846    }
847    
848    NTSTATUS
849    disk_create_notify(NTHANDLE handle, uint32 info_class)
850    {
851    
852            struct fileinfo *pfinfo;
853            NTSTATUS ret = STATUS_PENDING;
854    
855            /* printf("start disk_create_notify info_class %X\n", info_class); */
856    
857            pfinfo = &(g_fileinfo[handle]);
858            pfinfo->info_class = info_class;
859    
860            ret = NotifyInfo(handle, info_class, &pfinfo->notify);
861    
862            if (info_class & 0x1000)
863            {                       /* ???? */
864                    if (ret == STATUS_PENDING)
865                            return STATUS_SUCCESS;
866            }
867    
868            /* printf("disk_create_notify: num_entries %d\n", pfinfo->notify.num_entries); */
869    
870    
871            return ret;
872    
873    }
874    
875    static NTSTATUS
876    NotifyInfo(NTHANDLE handle, uint32 info_class, NOTIFY * p)
877    {
878            struct fileinfo *pfinfo;
879            struct stat buf;
880            struct dirent *dp;
881            char *fullname;
882            DIR *dpr;
883    
884            pfinfo = &(g_fileinfo[handle]);
885            if (fstat(handle, &buf) < 0)
886            {
887                    perror("NotifyInfo");
888                    return STATUS_ACCESS_DENIED;
889            }
890            p->modify_time = buf.st_mtime;
891            p->status_time = buf.st_ctime;
892            p->num_entries = 0;
893            p->total_time = 0;
894    
895    
896            dpr = opendir(pfinfo->path);
897            if (!dpr)
898            {
899                    perror("NotifyInfo");
900                    return STATUS_ACCESS_DENIED;
901            }
902    
903    
904            while ((dp = readdir(dpr)))
905            {
906                    if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
907                            continue;
908                    p->num_entries++;
909                    fullname = xmalloc(strlen(pfinfo->path) + strlen(dp->d_name) + 2);
910                    sprintf(fullname, "%s/%s", pfinfo->path, dp->d_name);
911    
912                    if (!stat(fullname, &buf))
913                    {
914                            p->total_time += (buf.st_mtime + buf.st_ctime);
915                    }
916    
917                    xfree(fullname);
918            }
919            closedir(dpr);
920    
921            return STATUS_PENDING;
922    }
923    
924  static FsInfoType *  static FsInfoType *
925  FsVolumeInfo(char *fpath)  FsVolumeInfo(char *fpath)
926  {  {
927    
 #ifdef HAVE_MNTENT_H  
928          FILE *fdfs;          FILE *fdfs;
         struct mntent *e;  
929          static FsInfoType info;          static FsInfoType info;
930    #ifdef HAVE_MNTENT_H
931            struct mntent *e;
932    #endif
933    
934          /* initialize */          /* initialize */
935          memset(&info, 0, sizeof(info));          memset(&info, 0, sizeof(info));
936          strcpy(info.label, "RDESKTOP");          strcpy(info.label, "RDESKTOP");
937          strcpy(info.type, "RDPFS");          strcpy(info.type, "RDPFS");
938    
939    #ifdef HAVE_MNTENT_H
940          fdfs = setmntent(MNTENT_PATH, "r");          fdfs = setmntent(MNTENT_PATH, "r");
941          if (!fdfs)          if (!fdfs)
942                  return &info;                  return &info;
# Line 787  FsVolumeInfo(char *fpath) Line 979  FsVolumeInfo(char *fpath)
979          }          }
980          endmntent(fdfs);          endmntent(fdfs);
981  #else  #else
         static FsInfoType info;  
   
982          /* initialize */          /* initialize */
983          memset(&info, 0, sizeof(info));          memset(&info, 0, sizeof(info));
984          strcpy(info.label, "RDESKTOP");          strcpy(info.label, "RDESKTOP");
# Line 977  disk_query_directory(NTHANDLE handle, ui Line 1167  disk_query_directory(NTHANDLE handle, ui
1167  static NTSTATUS  static NTSTATUS
1168  disk_device_control(NTHANDLE handle, uint32 request, STREAM in, STREAM out)  disk_device_control(NTHANDLE handle, uint32 request, STREAM in, STREAM out)
1169  {  {
         uint32 result;  
   
1170          if (((request >> 16) != 20) || ((request >> 16) != 9))          if (((request >> 16) != 20) || ((request >> 16) != 9))
1171                  return STATUS_INVALID_PARAMETER;                  return STATUS_INVALID_PARAMETER;
1172    

Legend:
Removed from v.785  
changed lines
  Added in v.827

  ViewVC Help
Powered by ViewVC 1.1.26