/[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 785 by astrand, Thu Oct 21 08:10:04 2004 UTC revision 795 by stargo, Wed Nov 3 13:56:52 2004 UTC
# 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 191  ftruncate_growable(int fd, off_t length) Line 193  ftruncate_growable(int fd, off_t length)
193          return 0;          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 241  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 279  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 335  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 375  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;
# Line 390  disk_close(NTHANDLE handle) Line 447  disk_close(NTHANDLE handle)
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;
# Line 428  disk_read(NTHANDLE handle, uint8 * data, Line 512  disk_read(NTHANDLE handle, uint8 * data,
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 551  disk_query_information(NTHANDLE handle, Line 638  disk_query_information(NTHANDLE handle,
638  NTSTATUS  NTSTATUS
639  disk_set_information(NTHANDLE 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 562  disk_set_information(NTHANDLE handle, ui Line 648  disk_set_information(NTHANDLE handle, ui
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 621  disk_set_information(NTHANDLE handle, ui Line 708  disk_set_information(NTHANDLE handle, ui
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 679  disk_set_information(NTHANDLE handle, ui Line 766  disk_set_information(NTHANDLE handle, ui
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. */  
   
                         //in_uint32_le(in, delete_on_close);  
770    
771                          /* 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);  
772    
773                          if ((pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE))       // remove a directory                          if (delete_on_close ||
774                                (pfinfo->
775                                 accessmask & (FILE_DELETE_ON_CLOSE | FILE_COMPLETE_IF_OPLOCKED)))
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 714  disk_set_information(NTHANDLE handle, ui Line 792  disk_set_information(NTHANDLE handle, ui
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                          if (ftruncate_growable(handle, length) != 0)                          if (ftruncate_growable(handle, length) != 0)
# Line 731  disk_set_information(NTHANDLE handle, ui Line 809  disk_set_information(NTHANDLE handle, ui
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 787  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 977  disk_query_directory(NTHANDLE handle, ui Line 1162  disk_query_directory(NTHANDLE handle, ui
1162  static NTSTATUS  static NTSTATUS
1163  disk_device_control(NTHANDLE 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.785  
changed lines
  Added in v.795

  ViewVC Help
Powered by ViewVC 1.1.26