/[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 783 by stargo, Fri Oct 15 18:02:45 2004 UTC revision 807 by stargo, Thu Dec 23 20:43:47 2004 UTC
# Line 66  Line 66 
66  #define STATFS_T statvfs  #define STATFS_T statvfs
67  #define F_NAMELEN(buf) ((buf).f_namemax)  #define F_NAMELEN(buf) ((buf).f_namemax)
68    
69    #elif (defined(__alpha) && !defined(linux))
70    #include <sys/mount.h>                /* osf1 statfs */
71    #define STATFS_FN(path, buf) (statfs(path,buf,sizeof(buf)))
72    #define STATFS_T statfs
73    #define F_NAMELEN(buf) (255)
74    
75  #else  #else
76  #include <sys/vfs.h>            /* linux statfs */  #include <sys/vfs.h>            /* linux statfs */
77  #include <mntent.h>  #include <mntent.h>
# Line 81  Line 87 
87  extern RDPDR_DEVICE g_rdpdr_device[];  extern RDPDR_DEVICE g_rdpdr_device[];
88    
89  FILEINFO g_fileinfo[MAX_OPEN_FILES];  FILEINFO g_fileinfo[MAX_OPEN_FILES];
90    BOOL g_notify_stamp = False;
91    
92  typedef struct  typedef struct
93  {  {
# Line 90  typedef struct Line 97  typedef struct
97          char type[256];          char type[256];
98  } FsInfoType;  } FsInfoType;
99    
100    static NTSTATUS NotifyInfo(NTHANDLE handle, uint32 info_class, NOTIFY * p);
101    
102  static time_t  static time_t
103  get_create_time(struct stat *st)  get_create_time(struct stat *st)
# Line 132  convert_1970_to_filetime(uint32 high, ui Line 140  convert_1970_to_filetime(uint32 high, ui
140    
141  }  }
142    
143    /* A wrapper for ftruncate which supports growing files, even if the
144       native ftruncate doesn't. This is needed on Linux FAT filesystems,
145       for example. */
146    static int
147    ftruncate_growable(int fd, off_t length)
148    {
149            int ret;
150            off_t pos;
151            static const char zero;
152    
153            /* Try the simple method first */
154            if ((ret = ftruncate(fd, length)) != -1)
155            {
156                    return ret;
157            }
158    
159            /*
160             * Some kind of error. Perhaps we were trying to grow. Retry
161             * in a safe way.
162             */
163    
164            /* Get current position */
165            if ((pos = lseek(fd, 0, SEEK_CUR)) == -1)
166            {
167                    perror("lseek");
168                    return -1;
169            }
170    
171            /* Seek to new size */
172            if (lseek(fd, length, SEEK_SET) == -1)
173            {
174                    perror("lseek");
175                    return -1;
176            }
177    
178            /* Write a zero */
179            if (write(fd, &zero, 1) == -1)
180            {
181                    perror("write");
182                    return -1;
183            }
184    
185            /* Truncate. This shouldn't fail. */
186            if (ftruncate(fd, length) == -1)
187            {
188                    perror("ftruncate");
189                    return -1;
190            }
191    
192            /* Restore position */
193            if (lseek(fd, pos, SEEK_SET) == -1)
194            {
195                    perror("lseek");
196                    return -1;
197            }
198    
199            return 0;
200    }
201    
202    /* Just like open(2), but if a open with O_EXCL fails, retry with
203       GUARDED semantics. This might be necessary because some filesystems
204       (such as NFS filesystems mounted from a unfsd server) doesn't
205       support O_EXCL. GUARDED semantics are subject to race conditions,
206       but we can live with that.
207    */
208    static int
209    open_weak_exclusive(const char *pathname, int flags, mode_t mode)
210    {
211            int ret;
212            struct stat statbuf;
213    
214            ret = open(pathname, flags, mode);
215            if (ret != -1 || !(flags & O_EXCL))
216            {
217                    /* Success, or not using O_EXCL */
218                    return ret;
219            }
220    
221            /* An error occured, and we are using O_EXCL. In case the FS
222               doesn't support O_EXCL, some kind of error will be
223               returned. Unfortunately, we don't know which one. Linux
224               2.6.8 seems to return 524, but I cannot find a documented
225               #define for this case. So, we'll return only on errors that
226               we know aren't related to O_EXCL. */
227            switch (errno)
228            {
229                    case EACCES:
230                    case EEXIST:
231                    case EINTR:
232                    case EISDIR:
233                    case ELOOP:
234                    case ENAMETOOLONG:
235                    case ENOENT:
236                    case ENOTDIR:
237                            return ret;
238            }
239    
240            /* Retry with GUARDED semantics */
241            if (stat(pathname, &statbuf) != -1)
242            {
243                    /* File exists */
244                    errno = EEXIST;
245                    return -1;
246            }
247            else
248            {
249                    return open(pathname, flags & ~O_EXCL, mode);
250            }
251    }
252    
253  /* Enumeration of devices from rdesktop.c        */  /* Enumeration of devices from rdesktop.c        */
254  /* returns numer of units found and initialized. */  /* returns numer of units found and initialized. */
# Line 182  disk_create(uint32 device_id, uint32 acc Line 299  disk_create(uint32 device_id, uint32 acc
299          flags = 0;          flags = 0;
300          mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;          mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
301    
302            if (*filename && filename[strlen(filename) - 1] == '/')
         if (filename[strlen(filename) - 1] == '/')  
303                  filename[strlen(filename) - 1] = 0;                  filename[strlen(filename) - 1] = 0;
304          sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename);          sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename);
305    
# Line 220  disk_create(uint32 device_id, uint32 acc Line 336  disk_create(uint32 device_id, uint32 acc
336                          break;                          break;
337          }          }
338    
339          //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);
340    
341          // Get information about file and set that flag ourselfs          // Get information about file and set that flag ourselfs
342          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 392  disk_create(uint32 device_id, uint32 acc
392                          flags |= O_RDONLY;                          flags |= O_RDONLY;
393                  }                  }
394    
395                  handle = open(path, flags, mode);                  handle = open_weak_exclusive(path, flags, mode);
396                  if (handle == -1)                  if (handle == -1)
397                  {                  {
398                          switch (errno)                          switch (errno)
# Line 316  disk_create(uint32 device_id, uint32 acc Line 432  disk_create(uint32 device_id, uint32 acc
432    
433          if (dirp)          if (dirp)
434                  g_fileinfo[handle].pdir = dirp;                  g_fileinfo[handle].pdir = dirp;
435            else
436                    g_fileinfo[handle].pdir = NULL;
437    
438          g_fileinfo[handle].device_id = device_id;          g_fileinfo[handle].device_id = device_id;
439          g_fileinfo[handle].flags_and_attributes = flags_and_attributes;          g_fileinfo[handle].flags_and_attributes = flags_and_attributes;
440            g_fileinfo[handle].accessmask = accessmask;
441          strncpy(g_fileinfo[handle].path, path, 255);          strncpy(g_fileinfo[handle].path, path, 255);
442            g_fileinfo[handle].delete_on_close = False;
443            g_notify_stamp = True;
444    
445          *phandle = handle;          *phandle = handle;
446          return STATUS_SUCCESS;          return STATUS_SUCCESS;
# Line 331  disk_close(NTHANDLE handle) Line 453  disk_close(NTHANDLE handle)
453    
454          pfinfo = &(g_fileinfo[handle]);          pfinfo = &(g_fileinfo[handle]);
455    
456          if (pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE)          g_notify_stamp = True;
457    
458            rdpdr_abort_io(handle, 0, STATUS_CANCELLED);
459    
460            if (pfinfo->pdir)
461          {          {
462                  closedir(pfinfo->pdir);                  if (closedir(pfinfo->pdir) < 0)
463                  //FIXME: Should check exit code                  {
464                            perror("closedir");
465                            return STATUS_INVALID_HANDLE;
466                    }
467    
468                    if (pfinfo->delete_on_close)
469                            if (rmdir(pfinfo->path) < 0)
470                            {
471                                    perror(pfinfo->path);
472                                    return STATUS_ACCESS_DENIED;
473                            }
474                    pfinfo->delete_on_close = False;
475          }          }
476          else          else
477          {          {
478                  close(handle);                  if (close(handle) < 0)
479                    {
480                            perror("close");
481                            return STATUS_INVALID_HANDLE;
482                    }
483                    if (pfinfo->delete_on_close)
484                            if (unlink(pfinfo->path) < 0)
485                            {
486                                    perror(pfinfo->path);
487                                    return STATUS_ACCESS_DENIED;
488                            }
489    
490                    pfinfo->delete_on_close = False;
491          }          }
492    
493          return STATUS_SUCCESS;          return STATUS_SUCCESS;
# Line 369  disk_read(NTHANDLE handle, uint8 * data, Line 518  disk_read(NTHANDLE handle, uint8 * data,
518                  switch (errno)                  switch (errno)
519                  {                  {
520                          case EISDIR:                          case EISDIR:
521                                  return STATUS_FILE_IS_A_DIRECTORY;                                  /* Implement 24 Byte directory read ??
522                                       with STATUS_NOT_IMPLEMENTED server doesn't read again */
523                                    /* return STATUS_FILE_IS_A_DIRECTORY; */
524                                    return STATUS_NOT_IMPLEMENTED;
525                          default:                          default:
526                                  perror("read");                                  perror("read");
527                                  return STATUS_INVALID_PARAMETER;                                  return STATUS_INVALID_PARAMETER;
# Line 492  disk_query_information(NTHANDLE handle, Line 644  disk_query_information(NTHANDLE handle,
644  NTSTATUS  NTSTATUS
645  disk_set_information(NTHANDLE handle, uint32 info_class, STREAM in, STREAM out)  disk_set_information(NTHANDLE handle, uint32 info_class, STREAM in, STREAM out)
646  {  {
647          uint32 device_id, length, file_attributes, ft_high, ft_low;          uint32 length, file_attributes, ft_high, ft_low, delete_on_close;
648          char newname[256], fullpath[256];          char newname[256], fullpath[256];
649          struct fileinfo *pfinfo;          struct fileinfo *pfinfo;
   
650          int mode;          int mode;
651          struct stat filestat;          struct stat filestat;
652          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(NTHANDLE handle, ui Line 654  disk_set_information(NTHANDLE handle, ui
654          struct STATFS_T stat_fs;          struct STATFS_T stat_fs;
655    
656          pfinfo = &(g_fileinfo[handle]);          pfinfo = &(g_fileinfo[handle]);
657            g_notify_stamp = True;
658    
659          switch (info_class)          switch (info_class)
660          {          {
# Line 562  disk_set_information(NTHANDLE handle, ui Line 714  disk_set_information(NTHANDLE handle, ui
714                                  printf("FileBasicInformation modification time %s",                                  printf("FileBasicInformation modification time %s",
715                                         ctime(&tvs.modtime));                                         ctime(&tvs.modtime));
716  #endif  #endif
717                                  if (utime(pfinfo->path, &tvs))                                  if (utime(pfinfo->path, &tvs) && errno != EPERM)
718                                          return STATUS_ACCESS_DENIED;                                          return STATUS_ACCESS_DENIED;
719                          }                          }
720    
# Line 620  disk_set_information(NTHANDLE handle, ui Line 772  disk_set_information(NTHANDLE handle, ui
772                             FileDispositionInformation requests with                             FileDispositionInformation requests with
773                             DeleteFile set to FALSE should unschedule                             DeleteFile set to FALSE should unschedule
774                             the delete. See                             the delete. See
775                             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);  
776    
777                          /* 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);  
778    
779                          if ((pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE))       // remove a directory                          if (delete_on_close ||
780                                (pfinfo->
781                                 accessmask & (FILE_DELETE_ON_CLOSE | FILE_COMPLETE_IF_OPLOCKED)))
782                          {                          {
783                                  if (rmdir(pfinfo->path) < 0)                                  pfinfo->delete_on_close = True;
                                         return STATUS_ACCESS_DENIED;  
784                          }                          }
                         else if (unlink(pfinfo->path) < 0)      // unlink a file  
                                 return STATUS_ACCESS_DENIED;  
785    
786                          break;                          break;
787    
# Line 655  disk_set_information(NTHANDLE handle, ui Line 798  disk_set_information(NTHANDLE handle, ui
798    
799                          /* prevents start of writing if not enough space left on device */                          /* prevents start of writing if not enough space left on device */
800                          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)
801                                  if (stat_fs.f_bsize * stat_fs.f_bfree < length)                                  if (stat_fs.f_bfree * stat_fs.f_bsize < length)
802                                          return STATUS_DISK_FULL;                                          return STATUS_DISK_FULL;
803    
804                          /* FIXME: Growing file with ftruncate doesn't                          if (ftruncate_growable(handle, length) != 0)
                            work with Linux FAT fs */  
                         if (ftruncate(handle, length) != 0)  
805                          {                          {
                                 perror("ftruncate");  
806                                  return STATUS_DISK_FULL;                                  return STATUS_DISK_FULL;
807                          }                          }
808    
# Line 675  disk_set_information(NTHANDLE handle, ui Line 815  disk_set_information(NTHANDLE handle, ui
815          return STATUS_SUCCESS;          return STATUS_SUCCESS;
816  }  }
817    
818    NTSTATUS
819    disk_check_notify(NTHANDLE handle)
820    {
821            struct fileinfo *pfinfo;
822            NTSTATUS status = STATUS_PENDING;
823    
824            NOTIFY notify;
825    
826            pfinfo = &(g_fileinfo[handle]);
827            if (!pfinfo->pdir)
828                    return STATUS_INVALID_DEVICE_REQUEST;
829    
830    
831    
832            status = NotifyInfo(handle, pfinfo->info_class, &notify);
833    
834            if (status != STATUS_PENDING)
835                    return status;
836    
837            if (memcmp(&pfinfo->notify, &notify, sizeof(NOTIFY)))
838            {
839                    //printf("disk_check_notify found changed event\n");
840                    memcpy(&pfinfo->notify, &notify, sizeof(NOTIFY));
841                    status = STATUS_NOTIFY_ENUM_DIR;
842            }
843    
844            return status;
845    
846    
847    }
848    
849    NTSTATUS
850    disk_create_notify(NTHANDLE handle, uint32 info_class)
851    {
852    
853            struct fileinfo *pfinfo;
854            NTSTATUS ret = STATUS_PENDING;
855    
856            /* printf("start disk_create_notify info_class %X\n", info_class); */
857    
858            pfinfo = &(g_fileinfo[handle]);
859            pfinfo->info_class = info_class;
860    
861            ret = NotifyInfo(handle, info_class, &pfinfo->notify);
862    
863            if (info_class & 0x1000)
864            {                       /* ???? */
865                    if (ret == STATUS_PENDING)
866                            return STATUS_SUCCESS;
867            }
868    
869            /* printf("disk_create_notify: num_entries %d\n", pfinfo->notify.num_entries); */
870    
871    
872            return ret;
873    
874    }
875    
876    static NTSTATUS
877    NotifyInfo(NTHANDLE handle, uint32 info_class, NOTIFY * p)
878    {
879            struct fileinfo *pfinfo;
880            struct stat buf;
881            struct dirent *dp;
882            char *fullname;
883            DIR *dpr;
884    
885            pfinfo = &(g_fileinfo[handle]);
886            if (fstat(handle, &buf) < 0)
887            {
888                    perror("NotifyInfo");
889                    return STATUS_ACCESS_DENIED;
890            }
891            p->modify_time = buf.st_mtime;
892            p->status_time = buf.st_ctime;
893            p->num_entries = 0;
894            p->total_time = 0;
895    
896    
897            dpr = opendir(pfinfo->path);
898            if (!dpr)
899            {
900                    perror("NotifyInfo");
901                    return STATUS_ACCESS_DENIED;
902            }
903    
904    
905            while ((dp = readdir(dpr)))
906            {
907                    if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
908                            continue;
909                    p->num_entries++;
910                    fullname = xmalloc(strlen(pfinfo->path) + strlen(dp->d_name) + 2);
911                    sprintf(fullname, "%s/%s", pfinfo->path, dp->d_name);
912    
913                    if (!stat(fullname, &buf))
914                    {
915                            p->total_time += (buf.st_mtime + buf.st_ctime);
916                    }
917    
918                    xfree(fullname);
919            }
920            closedir(dpr);
921    
922            return STATUS_PENDING;
923    }
924    
925  static FsInfoType *  static FsInfoType *
926  FsVolumeInfo(char *fpath)  FsVolumeInfo(char *fpath)
927  {  {
928    
 #ifdef HAVE_MNTENT_H  
929          FILE *fdfs;          FILE *fdfs;
         struct mntent *e;  
930          static FsInfoType info;          static FsInfoType info;
931    #ifdef HAVE_MNTENT_H
932            struct mntent *e;
933    #endif
934    
935          /* initialize */          /* initialize */
936          memset(&info, 0, sizeof(info));          memset(&info, 0, sizeof(info));
937          strcpy(info.label, "RDESKTOP");          strcpy(info.label, "RDESKTOP");
938          strcpy(info.type, "RDPFS");          strcpy(info.type, "RDPFS");
939    
940    #ifdef HAVE_MNTENT_H
941          fdfs = setmntent(MNTENT_PATH, "r");          fdfs = setmntent(MNTENT_PATH, "r");
942          if (!fdfs)          if (!fdfs)
943                  return &info;                  return &info;
# Line 731  FsVolumeInfo(char *fpath) Line 980  FsVolumeInfo(char *fpath)
980          }          }
981          endmntent(fdfs);          endmntent(fdfs);
982  #else  #else
         static FsInfoType info;  
   
983          /* initialize */          /* initialize */
984          memset(&info, 0, sizeof(info));          memset(&info, 0, sizeof(info));
985          strcpy(info.label, "RDESKTOP");          strcpy(info.label, "RDESKTOP");
# Line 921  disk_query_directory(NTHANDLE handle, ui Line 1168  disk_query_directory(NTHANDLE handle, ui
1168  static NTSTATUS  static NTSTATUS
1169  disk_device_control(NTHANDLE handle, uint32 request, STREAM in, STREAM out)  disk_device_control(NTHANDLE handle, uint32 request, STREAM in, STREAM out)
1170  {  {
         uint32 result;  
   
1171          if (((request >> 16) != 20) || ((request >> 16) != 9))          if (((request >> 16) != 20) || ((request >> 16) != 9))
1172                  return STATUS_INVALID_PARAMETER;                  return STATUS_INVALID_PARAMETER;
1173    

Legend:
Removed from v.783  
changed lines
  Added in v.807

  ViewVC Help
Powered by ViewVC 1.1.26