/[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 747 by astrand, Mon Aug 9 13:50:41 2004 UTC revision 879 by astrand, Sun Apr 3 18:08:05 2005 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)
38  #endif  #endif
39    
40  /* TODO: let autoconf figure out everything below... */  /* TODO: Fix mntent-handling for solaris
41  #if (defined(sun) && (defined(__svr4__) || defined(__SVR4)))   * #include <sys/mntent.h> */
42  #define SOLARIS  #if (defined(HAVE_MNTENT_H) && defined(HAVE_SETMNTENT))
43    #include <mntent.h>
44    #define MNTENT_PATH "/etc/mtab"
45    #define USE_SETMNTENT
46  #endif  #endif
47    
48  #if (defined(SOLARIS) || defined (__hpux) || defined(__BEOS__))  #ifdef HAVE_SYS_VFS_H
49  #include <sys/statvfs.h>        /* solaris statvfs */  #include <sys/vfs.h>
50  /* TODO: Fix mntent-handling for solaris/hpux  #endif
51   * #include <sys/mntent.h> */  
52  #undef HAVE_MNTENT_H  #ifdef HAVE_SYS_STATVFS_H
53  #define MNTENT_PATH "/etc/mnttab"  #include <sys/statvfs.h>
54  #define STATFS_FN(path, buf) (statvfs(path,buf))  #endif
 #define STATFS_T statvfs  
 #define F_NAMELEN(buf) ((buf).f_namemax)  
55    
56  #elif (defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__))  #ifdef HAVE_SYS_STATFS_H
57    #include <sys/statfs.h>
58    #endif
59    
60    #ifdef HAVE_SYS_PARAM_H
61  #include <sys/param.h>  #include <sys/param.h>
62    #endif
63    
64    #ifdef HAVE_SYS_MOUNT_H
65  #include <sys/mount.h>  #include <sys/mount.h>
66  #define STATFS_FN(path, buf) (statfs(path,buf))  #endif
67    
68    #include "rdesktop.h"
69    
70    #ifdef STAT_STATFS3_OSF1
71    #define STATFS_FN(path, buf) (statfs(path,buf,sizeof(buf)))
72  #define STATFS_T statfs  #define STATFS_T statfs
73  #define F_NAMELEN(buf) (NAME_MAX)  #define USE_STATFS
74    #endif
75    
76  #elif (defined(__SGI_IRIX__))  #ifdef STAT_STATVFS
 #include <sys/types.h>  
 #include <sys/statvfs.h>  
77  #define STATFS_FN(path, buf) (statvfs(path,buf))  #define STATFS_FN(path, buf) (statvfs(path,buf))
78  #define STATFS_T statvfs  #define STATFS_T statvfs
79  #define F_NAMELEN(buf) ((buf).f_namemax)  #define USE_STATVFS
80    #endif
81    
82  #else  #ifdef STAT_STATVFS64
83  #include <sys/vfs.h>            /* linux statfs */  #define STATFS_FN(path, buf) (statvfs64(path,buf))
84  #include <mntent.h>  #define STATFS_T statvfs64
85  #define HAVE_MNTENT_H  #define USE_STATVFS
86  #define MNTENT_PATH "/etc/mtab"  #endif
87    
88    #if (defined(STAT_STATFS2_FS_DATA) || defined(STAT_STATFS2_BSIZE) || defined(STAT_STATFS2_FSIZE))
89  #define STATFS_FN(path, buf) (statfs(path,buf))  #define STATFS_FN(path, buf) (statfs(path,buf))
90  #define STATFS_T statfs  #define STATFS_T statfs
91    #define USE_STATFS
92    #endif
93    
94    #ifdef STAT_STATFS4
95    #define STATFS_FN(path, buf) (statfs(path,buf,sizeof(buf),0))
96    #define STATFS_T statfs
97    #define USE_STATFS
98    #endif
99    
100    #if ((defined(USE_STATFS) && defined(HAVE_STRUCT_STATFS_F_NAMEMAX)) || (defined(USE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_NAMEMAX)))
101    #define F_NAMELEN(buf) ((buf).f_namemax)
102    #endif
103    
104    #if ((defined(USE_STATFS) && defined(HAVE_STRUCT_STATFS_F_NAMELEN)) || (defined(USE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_NAMELEN)))
105  #define F_NAMELEN(buf) ((buf).f_namelen)  #define F_NAMELEN(buf) ((buf).f_namelen)
106  #endif  #endif
107    
108  #include "rdesktop.h"  #ifndef F_NAMELEN
109    #define F_NAMELEN(buf) (255)
110    #endif
111    
112    /* Dummy statfs fallback */
113    #ifndef STATFS_T
114    struct dummy_statfs_t
115    {
116            long f_bfree;
117            long f_bsize;
118            long f_blocks;
119            int f_namelen;
120            int f_namemax;
121    };
122    
123    int
124    dummy_statfs(struct dummy_statfs_t *buf)
125    {
126            buf->f_blocks = 262144;
127            buf->f_bfree = 131072;
128            buf->f_bsize = 512;
129            buf->f_namelen = 255;
130            buf->f_namemax = 255;
131    
132            return 0;
133    }
134    
135    #define STATFS_T dummy_statfs_t
136    #define STATFS_FN(path,buf) (dummy_statfs(buf))
137    #endif
138    
139  extern RDPDR_DEVICE g_rdpdr_device[];  extern RDPDR_DEVICE g_rdpdr_device[];
140    
141  FILEINFO g_fileinfo[MAX_OPEN_FILES];  FILEINFO g_fileinfo[MAX_OPEN_FILES];
142    BOOL g_notify_stamp = False;
143    
144  typedef struct  typedef struct
145  {  {
# Line 90  typedef struct Line 149  typedef struct
149          char type[256];          char type[256];
150  } FsInfoType;  } FsInfoType;
151    
152    static NTSTATUS NotifyInfo(NTHANDLE handle, uint32 info_class, NOTIFY * p);
153    
154  static time_t  static time_t
155  get_create_time(struct stat *st)  get_create_time(struct stat *st)
# Line 132  convert_1970_to_filetime(uint32 high, ui Line 192  convert_1970_to_filetime(uint32 high, ui
192    
193  }  }
194    
195    /* A wrapper for ftruncate which supports growing files, even if the
196       native ftruncate doesn't. This is needed on Linux FAT filesystems,
197       for example. */
198    static int
199    ftruncate_growable(int fd, off_t length)
200    {
201            int ret;
202            off_t pos;
203            static const char zero;
204    
205            /* Try the simple method first */
206            if ((ret = ftruncate(fd, length)) != -1)
207            {
208                    return ret;
209            }
210    
211            /*
212             * Some kind of error. Perhaps we were trying to grow. Retry
213             * in a safe way.
214             */
215    
216            /* Get current position */
217            if ((pos = lseek(fd, 0, SEEK_CUR)) == -1)
218            {
219                    perror("lseek");
220                    return -1;
221            }
222    
223            /* Seek to new size */
224            if (lseek(fd, length, SEEK_SET) == -1)
225            {
226                    perror("lseek");
227                    return -1;
228            }
229    
230            /* Write a zero */
231            if (write(fd, &zero, 1) == -1)
232            {
233                    perror("write");
234                    return -1;
235            }
236    
237            /* Truncate. This shouldn't fail. */
238            if (ftruncate(fd, length) == -1)
239            {
240                    perror("ftruncate");
241                    return -1;
242            }
243    
244            /* Restore position */
245            if (lseek(fd, pos, SEEK_SET) == -1)
246            {
247                    perror("lseek");
248                    return -1;
249            }
250    
251            return 0;
252    }
253    
254    /* Just like open(2), but if a open with O_EXCL fails, retry with
255       GUARDED semantics. This might be necessary because some filesystems
256       (such as NFS filesystems mounted from a unfsd server) doesn't
257       support O_EXCL. GUARDED semantics are subject to race conditions,
258       but we can live with that.
259    */
260    static int
261    open_weak_exclusive(const char *pathname, int flags, mode_t mode)
262    {
263            int ret;
264            struct stat statbuf;
265    
266            ret = open(pathname, flags, mode);
267            if (ret != -1 || !(flags & O_EXCL))
268            {
269                    /* Success, or not using O_EXCL */
270                    return ret;
271            }
272    
273            /* An error occured, and we are using O_EXCL. In case the FS
274               doesn't support O_EXCL, some kind of error will be
275               returned. Unfortunately, we don't know which one. Linux
276               2.6.8 seems to return 524, but I cannot find a documented
277               #define for this case. So, we'll return only on errors that
278               we know aren't related to O_EXCL. */
279            switch (errno)
280            {
281                    case EACCES:
282                    case EEXIST:
283                    case EINTR:
284                    case EISDIR:
285                    case ELOOP:
286                    case ENAMETOOLONG:
287                    case ENOENT:
288                    case ENOTDIR:
289                            return ret;
290            }
291    
292            /* Retry with GUARDED semantics */
293            if (stat(pathname, &statbuf) != -1)
294            {
295                    /* File exists */
296                    errno = EEXIST;
297                    return -1;
298            }
299            else
300            {
301                    return open(pathname, flags & ~O_EXCL, mode);
302            }
303    }
304    
305  /* Enumeration of devices from rdesktop.c        */  /* Enumeration of devices from rdesktop.c        */
306  /* returns numer of units found and initialized. */  /* returns numer of units found and initialized. */
# Line 144  disk_enum_devices(uint32 * id, char *opt Line 313  disk_enum_devices(uint32 * id, char *opt
313          char *pos2;          char *pos2;
314          int count = 0;          int count = 0;
315    
316          // skip the first colon          /* skip the first colon */
317          optarg++;          optarg++;
318          while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)          while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
319          {          {
320                  pos2 = next_arg(optarg, '=');                  pos2 = next_arg(optarg, '=');
321    
322                  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);
323                  if (strlen(optarg) > 8)                  if (strlen(optarg) > (sizeof(g_rdpdr_device[*id].name) - 1))
324                          fprintf(stderr, "share name %s truncated to %s\n", optarg,                          fprintf(stderr, "share name %s truncated to %s\n", optarg,
325                                  g_rdpdr_device[*id].name);                                  g_rdpdr_device[*id].name);
326    
# Line 169  disk_enum_devices(uint32 * id, char *opt Line 338  disk_enum_devices(uint32 * id, char *opt
338  /* Opens or creates a file or directory */  /* Opens or creates a file or directory */
339  static NTSTATUS  static NTSTATUS
340  disk_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition,  disk_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition,
341              uint32 flags_and_attributes, char *filename, HANDLE * phandle)              uint32 flags_and_attributes, char *filename, NTHANDLE * phandle)
342  {  {
343          HANDLE handle;          NTHANDLE handle;
344          DIR *dirp;          DIR *dirp;
345          int flags, mode;          int flags, mode;
346          char path[256];          char path[256];
# Line 182  disk_create(uint32 device_id, uint32 acc Line 351  disk_create(uint32 device_id, uint32 acc
351          flags = 0;          flags = 0;
352          mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;          mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
353    
354            if (*filename && filename[strlen(filename) - 1] == '/')
         if (filename[strlen(filename) - 1] == '/')  
355                  filename[strlen(filename) - 1] = 0;                  filename[strlen(filename) - 1] = 0;
356          sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename);          sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename);
357    
# Line 191  disk_create(uint32 device_id, uint32 acc Line 359  disk_create(uint32 device_id, uint32 acc
359          {          {
360                  case CREATE_ALWAYS:                  case CREATE_ALWAYS:
361    
362                          // Delete existing file/link.                          /* Delete existing file/link. */
363                          unlink(path);                          unlink(path);
364                          flags |= O_CREAT;                          flags |= O_CREAT;
365                          break;                          break;
366    
367                  case CREATE_NEW:                  case CREATE_NEW:
368    
369                          // If the file already exists, then fail.                          /* If the file already exists, then fail. */
370                          flags |= O_CREAT | O_EXCL;                          flags |= O_CREAT | O_EXCL;
371                          break;                          break;
372    
373                  case OPEN_ALWAYS:                  case OPEN_ALWAYS:
374    
375                          // Create if not already exists.                          /* Create if not already exists. */
376                          flags |= O_CREAT;                          flags |= O_CREAT;
377                          break;                          break;
378    
379                  case OPEN_EXISTING:                  case OPEN_EXISTING:
380    
381                          // Default behaviour                          /* Default behaviour */
382                          break;                          break;
383    
384                  case TRUNCATE_EXISTING:                  case TRUNCATE_EXISTING:
385    
386                          // If the file does not exist, then fail.                          /* If the file does not exist, then fail. */
387                          flags |= O_TRUNC;                          flags |= O_TRUNC;
388                          break;                          break;
389          }          }
390    
391          //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); */
392    
393          // Get information about file and set that flag ourselfs          /* Get information about file and set that flag ourselfs */
394          if ((stat(path, &filestat) == 0) && (S_ISDIR(filestat.st_mode)))          if ((stat(path, &filestat) == 0) && (S_ISDIR(filestat.st_mode)))
395          {          {
396                  if (flags_and_attributes & FILE_NON_DIRECTORY_FILE)                  if (flags_and_attributes & FILE_NON_DIRECTORY_FILE)
# Line 276  disk_create(uint32 device_id, uint32 acc Line 444  disk_create(uint32 device_id, uint32 acc
444                          flags |= O_RDONLY;                          flags |= O_RDONLY;
445                  }                  }
446    
447                  handle = open(path, flags, mode);                  handle = open_weak_exclusive(path, flags, mode);
448                  if (handle == -1)                  if (handle == -1)
449                  {                  {
450                          switch (errno)                          switch (errno)
# Line 316  disk_create(uint32 device_id, uint32 acc Line 484  disk_create(uint32 device_id, uint32 acc
484    
485          if (dirp)          if (dirp)
486                  g_fileinfo[handle].pdir = dirp;                  g_fileinfo[handle].pdir = dirp;
487            else
488                    g_fileinfo[handle].pdir = NULL;
489    
490          g_fileinfo[handle].device_id = device_id;          g_fileinfo[handle].device_id = device_id;
491          g_fileinfo[handle].flags_and_attributes = flags_and_attributes;          g_fileinfo[handle].flags_and_attributes = flags_and_attributes;
492            g_fileinfo[handle].accessmask = accessmask;
493          strncpy(g_fileinfo[handle].path, path, 255);          strncpy(g_fileinfo[handle].path, path, 255);
494            g_fileinfo[handle].delete_on_close = False;
495            g_notify_stamp = True;
496    
497          *phandle = handle;          *phandle = handle;
498          return STATUS_SUCCESS;          return STATUS_SUCCESS;
499  }  }
500    
501  static NTSTATUS  static NTSTATUS
502  disk_close(HANDLE handle)  disk_close(NTHANDLE handle)
503  {  {
504          struct fileinfo *pfinfo;          struct fileinfo *pfinfo;
505    
506          pfinfo = &(g_fileinfo[handle]);          pfinfo = &(g_fileinfo[handle]);
507    
508          if (pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE)          g_notify_stamp = True;
509    
510            rdpdr_abort_io(handle, 0, STATUS_CANCELLED);
511    
512            if (pfinfo->pdir)
513          {          {
514                  closedir(pfinfo->pdir);                  if (closedir(pfinfo->pdir) < 0)
515                  //FIXME: Should check exit code                  {
516                            perror("closedir");
517                            return STATUS_INVALID_HANDLE;
518                    }
519    
520                    if (pfinfo->delete_on_close)
521                            if (rmdir(pfinfo->path) < 0)
522                            {
523                                    perror(pfinfo->path);
524                                    return STATUS_ACCESS_DENIED;
525                            }
526                    pfinfo->delete_on_close = False;
527          }          }
528          else          else
529          {          {
530                  close(handle);                  if (close(handle) < 0)
531                    {
532                            perror("close");
533                            return STATUS_INVALID_HANDLE;
534                    }
535                    if (pfinfo->delete_on_close)
536                            if (unlink(pfinfo->path) < 0)
537                            {
538                                    perror(pfinfo->path);
539                                    return STATUS_ACCESS_DENIED;
540                            }
541    
542                    pfinfo->delete_on_close = False;
543          }          }
544    
545          return STATUS_SUCCESS;          return STATUS_SUCCESS;
546  }  }
547    
548  static NTSTATUS  static NTSTATUS
549  disk_read(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)  disk_read(NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
550  {  {
551          int n;          int n;
552    
# Line 369  disk_read(HANDLE handle, uint8 * data, u Line 570  disk_read(HANDLE handle, uint8 * data, u
570                  switch (errno)                  switch (errno)
571                  {                  {
572                          case EISDIR:                          case EISDIR:
573                                  return STATUS_FILE_IS_A_DIRECTORY;                                  /* Implement 24 Byte directory read ??
574                                       with STATUS_NOT_IMPLEMENTED server doesn't read again */
575                                    /* return STATUS_FILE_IS_A_DIRECTORY; */
576                                    return STATUS_NOT_IMPLEMENTED;
577                          default:                          default:
578                                  perror("read");                                  perror("read");
579                                  return STATUS_INVALID_PARAMETER;                                  return STATUS_INVALID_PARAMETER;
# Line 382  disk_read(HANDLE handle, uint8 * data, u Line 586  disk_read(HANDLE handle, uint8 * data, u
586  }  }
587    
588  static NTSTATUS  static NTSTATUS
589  disk_write(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)  disk_write(NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
590  {  {
591          int n;          int n;
592    
# Line 409  disk_write(HANDLE handle, uint8 * data, Line 613  disk_write(HANDLE handle, uint8 * data,
613  }  }
614    
615  NTSTATUS  NTSTATUS
616  disk_query_information(HANDLE handle, uint32 info_class, STREAM out)  disk_query_information(NTHANDLE handle, uint32 info_class, STREAM out)
617  {  {
618          uint32 file_attributes, ft_high, ft_low;          uint32 file_attributes, ft_high, ft_low;
619          struct stat filestat;          struct stat filestat;
# Line 417  disk_query_information(HANDLE handle, ui Line 621  disk_query_information(HANDLE handle, ui
621    
622          path = g_fileinfo[handle].path;          path = g_fileinfo[handle].path;
623    
624          // Get information about file          /* Get information about file */
625          if (fstat(handle, &filestat) != 0)          if (fstat(handle, &filestat) != 0)
626          {          {
627                  perror("stat");                  perror("stat");
# Line 425  disk_query_information(HANDLE handle, ui Line 629  disk_query_information(HANDLE handle, ui
629                  return STATUS_ACCESS_DENIED;                  return STATUS_ACCESS_DENIED;
630          }          }
631    
632          // Set file attributes          /* Set file attributes */
633          file_attributes = 0;          file_attributes = 0;
634          if (S_ISDIR(filestat.st_mode))          if (S_ISDIR(filestat.st_mode))
635                  file_attributes |= FILE_ATTRIBUTE_DIRECTORY;                  file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
# Line 440  disk_query_information(HANDLE handle, ui Line 644  disk_query_information(HANDLE handle, ui
644          if (!(filestat.st_mode & S_IWUSR))          if (!(filestat.st_mode & S_IWUSR))
645                  file_attributes |= FILE_ATTRIBUTE_READONLY;                  file_attributes |= FILE_ATTRIBUTE_READONLY;
646    
647          // Return requested data          /* Return requested data */
648          switch (info_class)          switch (info_class)
649          {          {
650                  case FileBasicInformation:                  case FileBasicInformation:
651                          seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high,                          seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high,
652                                                         &ft_low);                                                         &ft_low);
653                          out_uint32_le(out, ft_low);     //create_access_time                          out_uint32_le(out, ft_low);     /* create_access_time */
654                          out_uint32_le(out, ft_high);                          out_uint32_le(out, ft_high);
655    
656                          seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low);                          seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low);
657                          out_uint32_le(out, ft_low);     //last_access_time                          out_uint32_le(out, ft_low);     /* last_access_time */
658                          out_uint32_le(out, ft_high);                          out_uint32_le(out, ft_high);
659    
660                          seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low);                          seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low);
661                          out_uint32_le(out, ft_low);     //last_write_time                          out_uint32_le(out, ft_low);     /* last_write_time */
662                          out_uint32_le(out, ft_high);                          out_uint32_le(out, ft_high);
663    
664                          seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low);                          seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low);
665                          out_uint32_le(out, ft_low);     //last_change_time                          out_uint32_le(out, ft_low);     /* last_change_time */
666                          out_uint32_le(out, ft_high);                          out_uint32_le(out, ft_high);
667    
668                          out_uint32_le(out, file_attributes);                          out_uint32_le(out, file_attributes);
# Line 466  disk_query_information(HANDLE handle, ui Line 670  disk_query_information(HANDLE handle, ui
670    
671                  case FileStandardInformation:                  case FileStandardInformation:
672    
673                          out_uint32_le(out, filestat.st_size);   //Allocation size                          out_uint32_le(out, filestat.st_size);   /* Allocation size */
674                          out_uint32_le(out, 0);                          out_uint32_le(out, 0);
675                          out_uint32_le(out, filestat.st_size);   //End of file                          out_uint32_le(out, filestat.st_size);   /* End of file */
676                          out_uint32_le(out, 0);                          out_uint32_le(out, 0);
677                          out_uint32_le(out, filestat.st_nlink);  //Number of links                          out_uint32_le(out, filestat.st_nlink);  /* Number of links */
678                          out_uint8(out, 0);      //Delete pending                          out_uint8(out, 0);      /* Delete pending */
679                          out_uint8(out, S_ISDIR(filestat.st_mode) ? 1 : 0);      //Directory                          out_uint8(out, S_ISDIR(filestat.st_mode) ? 1 : 0);      /* Directory */
680                          break;                          break;
681    
682                  case FileObjectIdInformation:                  case FileObjectIdInformation:
# Line 490  disk_query_information(HANDLE handle, ui Line 694  disk_query_information(HANDLE handle, ui
694  }  }
695    
696  NTSTATUS  NTSTATUS
697  disk_set_information(HANDLE handle, uint32 info_class, STREAM in, STREAM out)  disk_set_information(NTHANDLE handle, uint32 info_class, STREAM in, STREAM out)
698  {  {
699          uint32 device_id, length, file_attributes, ft_high, ft_low;          uint32 length, file_attributes, ft_high, ft_low, delete_on_close;
700          char newname[256], fullpath[256];          char newname[256], fullpath[256];
701          struct fileinfo *pfinfo;          struct fileinfo *pfinfo;
   
702          int mode;          int mode;
703          struct stat filestat;          struct stat filestat;
704          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 706  disk_set_information(HANDLE handle, uint
706          struct STATFS_T stat_fs;          struct STATFS_T stat_fs;
707    
708          pfinfo = &(g_fileinfo[handle]);          pfinfo = &(g_fileinfo[handle]);
709            g_notify_stamp = True;
710    
711          switch (info_class)          switch (info_class)
712          {          {
# Line 512  disk_set_information(HANDLE handle, uint Line 716  disk_set_information(HANDLE handle, uint
716                          in_uint8s(in, 4);       /* Handle of root dir? */                          in_uint8s(in, 4);       /* Handle of root dir? */
717                          in_uint8s(in, 24);      /* unknown */                          in_uint8s(in, 24);      /* unknown */
718    
719                          // CreationTime                          /* CreationTime */
720                          in_uint32_le(in, ft_low);                          in_uint32_le(in, ft_low);
721                          in_uint32_le(in, ft_high);                          in_uint32_le(in, ft_high);
722    
723                          // AccessTime                          /* AccessTime */
724                          in_uint32_le(in, ft_low);                          in_uint32_le(in, ft_low);
725                          in_uint32_le(in, ft_high);                          in_uint32_le(in, ft_high);
726                          if (ft_low || ft_high)                          if (ft_low || ft_high)
727                                  access_time = convert_1970_to_filetime(ft_high, ft_low);                                  access_time = convert_1970_to_filetime(ft_high, ft_low);
728    
729                          // WriteTime                          /* WriteTime */
730                          in_uint32_le(in, ft_low);                          in_uint32_le(in, ft_low);
731                          in_uint32_le(in, ft_high);                          in_uint32_le(in, ft_high);
732                          if (ft_low || ft_high)                          if (ft_low || ft_high)
733                                  write_time = convert_1970_to_filetime(ft_high, ft_low);                                  write_time = convert_1970_to_filetime(ft_high, ft_low);
734    
735                          // ChangeTime                          /* ChangeTime */
736                          in_uint32_le(in, ft_low);                          in_uint32_le(in, ft_low);
737                          in_uint32_le(in, ft_high);                          in_uint32_le(in, ft_high);
738                          if (ft_low || ft_high)                          if (ft_low || ft_high)
# Line 562  disk_set_information(HANDLE handle, uint Line 766  disk_set_information(HANDLE handle, uint
766                                  printf("FileBasicInformation modification time %s",                                  printf("FileBasicInformation modification time %s",
767                                         ctime(&tvs.modtime));                                         ctime(&tvs.modtime));
768  #endif  #endif
769                                  if (utime(pfinfo->path, &tvs))                                  if (utime(pfinfo->path, &tvs) && errno != EPERM)
770                                          return STATUS_ACCESS_DENIED;                                          return STATUS_ACCESS_DENIED;
771                          }                          }
772    
773                          if (!file_attributes)                          if (!file_attributes)
774                                  break;  // not valid                                  break;  /* not valid */
775    
776                          mode = filestat.st_mode;                          mode = filestat.st_mode;
777    
# Line 620  disk_set_information(HANDLE handle, uint Line 824  disk_set_information(HANDLE handle, uint
824                             FileDispositionInformation requests with                             FileDispositionInformation requests with
825                             DeleteFile set to FALSE should unschedule                             DeleteFile set to FALSE should unschedule
826                             the delete. See                             the delete. See
827                             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);  
828    
829                          /* 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);  
830    
831                          if ((pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE))       // remove a directory                          if (delete_on_close ||
832                                (pfinfo->
833                                 accessmask & (FILE_DELETE_ON_CLOSE | FILE_COMPLETE_IF_OPLOCKED)))
834                          {                          {
835                                  if (rmdir(pfinfo->path) < 0)                                  pfinfo->delete_on_close = True;
                                         return STATUS_ACCESS_DENIED;  
836                          }                          }
                         else if (unlink(pfinfo->path) < 0)      // unlink a file  
                                 return STATUS_ACCESS_DENIED;  
837    
838                          break;                          break;
839    
# Line 655  disk_set_information(HANDLE handle, uint Line 850  disk_set_information(HANDLE handle, uint
850    
851                          /* prevents start of writing if not enough space left on device */                          /* prevents start of writing if not enough space left on device */
852                          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)
853                                  if (stat_fs.f_bsize * stat_fs.f_bfree < length)                                  if (stat_fs.f_bfree * stat_fs.f_bsize < length)
854                                          return STATUS_DISK_FULL;                                          return STATUS_DISK_FULL;
855    
856                          /* FIXME: Growing file with ftruncate doesn't                          if (ftruncate_growable(handle, length) != 0)
                            work with Linux FAT fs */  
                         if (ftruncate(handle, length) != 0)  
857                          {                          {
                                 perror("ftruncate");  
858                                  return STATUS_DISK_FULL;                                  return STATUS_DISK_FULL;
859                          }                          }
860    
# Line 675  disk_set_information(HANDLE handle, uint Line 867  disk_set_information(HANDLE handle, uint
867          return STATUS_SUCCESS;          return STATUS_SUCCESS;
868  }  }
869    
870    NTSTATUS
871    disk_check_notify(NTHANDLE handle)
872    {
873            struct fileinfo *pfinfo;
874            NTSTATUS status = STATUS_PENDING;
875    
876            NOTIFY notify;
877    
878            pfinfo = &(g_fileinfo[handle]);
879            if (!pfinfo->pdir)
880                    return STATUS_INVALID_DEVICE_REQUEST;
881    
882    
883    
884            status = NotifyInfo(handle, pfinfo->info_class, &notify);
885    
886            if (status != STATUS_PENDING)
887                    return status;
888    
889            if (memcmp(&pfinfo->notify, &notify, sizeof(NOTIFY)))
890            {
891                    /*printf("disk_check_notify found changed event\n"); */
892                    memcpy(&pfinfo->notify, &notify, sizeof(NOTIFY));
893                    status = STATUS_NOTIFY_ENUM_DIR;
894            }
895    
896            return status;
897    
898    
899    }
900    
901    NTSTATUS
902    disk_create_notify(NTHANDLE handle, uint32 info_class)
903    {
904    
905            struct fileinfo *pfinfo;
906            NTSTATUS ret = STATUS_PENDING;
907    
908            /* printf("start disk_create_notify info_class %X\n", info_class); */
909    
910            pfinfo = &(g_fileinfo[handle]);
911            pfinfo->info_class = info_class;
912    
913            ret = NotifyInfo(handle, info_class, &pfinfo->notify);
914    
915            if (info_class & 0x1000)
916            {                       /* ???? */
917                    if (ret == STATUS_PENDING)
918                            return STATUS_SUCCESS;
919            }
920    
921            /* printf("disk_create_notify: num_entries %d\n", pfinfo->notify.num_entries); */
922    
923    
924            return ret;
925    
926    }
927    
928    static NTSTATUS
929    NotifyInfo(NTHANDLE handle, uint32 info_class, NOTIFY * p)
930    {
931            struct fileinfo *pfinfo;
932            struct stat buf;
933            struct dirent *dp;
934            char *fullname;
935            DIR *dpr;
936    
937            pfinfo = &(g_fileinfo[handle]);
938            if (fstat(handle, &buf) < 0)
939            {
940                    perror("NotifyInfo");
941                    return STATUS_ACCESS_DENIED;
942            }
943            p->modify_time = buf.st_mtime;
944            p->status_time = buf.st_ctime;
945            p->num_entries = 0;
946            p->total_time = 0;
947    
948    
949            dpr = opendir(pfinfo->path);
950            if (!dpr)
951            {
952                    perror("NotifyInfo");
953                    return STATUS_ACCESS_DENIED;
954            }
955    
956    
957            while ((dp = readdir(dpr)))
958            {
959                    if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
960                            continue;
961                    p->num_entries++;
962                    fullname = xmalloc(strlen(pfinfo->path) + strlen(dp->d_name) + 2);
963                    sprintf(fullname, "%s/%s", pfinfo->path, dp->d_name);
964    
965                    if (!stat(fullname, &buf))
966                    {
967                            p->total_time += (buf.st_mtime + buf.st_ctime);
968                    }
969    
970                    xfree(fullname);
971            }
972            closedir(dpr);
973    
974            return STATUS_PENDING;
975    }
976    
977  static FsInfoType *  static FsInfoType *
978  FsVolumeInfo(char *fpath)  FsVolumeInfo(char *fpath)
979  {  {
980    
981  #ifdef HAVE_MNTENT_H          static FsInfoType info;
982    #ifdef USE_SETMNTENT
983          FILE *fdfs;          FILE *fdfs;
984          struct mntent *e;          struct mntent *e;
985          static FsInfoType info;  #endif
986    
987          /* initialize */          /* initialize */
988          memset(&info, 0, sizeof(info));          memset(&info, 0, sizeof(info));
989          strcpy(info.label, "RDESKTOP");          strcpy(info.label, "RDESKTOP");
990          strcpy(info.type, "RDPFS");          strcpy(info.type, "RDPFS");
991    
992    #ifdef USE_SETMNTENT
993          fdfs = setmntent(MNTENT_PATH, "r");          fdfs = setmntent(MNTENT_PATH, "r");
994          if (!fdfs)          if (!fdfs)
995                  return &info;                  return &info;
# Line 722  FsVolumeInfo(char *fpath) Line 1023  FsVolumeInfo(char *fpath)
1023                                                  read(fd, buf, sizeof(buf));                                                  read(fd, buf, sizeof(buf));
1024                                                  strncpy(info.label, buf + 41, 32);                                                  strncpy(info.label, buf + 41, 32);
1025                                                  info.label[32] = '\0';                                                  info.label[32] = '\0';
1026                                                  //info.Serial = (buf[128]<<24)+(buf[127]<<16)+(buf[126]<<8)+buf[125];                                                  /* info.Serial = (buf[128]<<24)+(buf[127]<<16)+(buf[126]<<8)+buf[125]; */
1027                                          }                                          }
1028                                          close(fd);                                          close(fd);
1029                                  }                                  }
# Line 731  FsVolumeInfo(char *fpath) Line 1032  FsVolumeInfo(char *fpath)
1032          }          }
1033          endmntent(fdfs);          endmntent(fdfs);
1034  #else  #else
         static FsInfoType info;  
   
1035          /* initialize */          /* initialize */
1036          memset(&info, 0, sizeof(info));          memset(&info, 0, sizeof(info));
1037          strcpy(info.label, "RDESKTOP");          strcpy(info.label, "RDESKTOP");
# Line 744  FsVolumeInfo(char *fpath) Line 1043  FsVolumeInfo(char *fpath)
1043    
1044    
1045  NTSTATUS  NTSTATUS
1046  disk_query_volume_information(HANDLE handle, uint32 info_class, STREAM out)  disk_query_volume_information(NTHANDLE handle, uint32 info_class, STREAM out)
1047  {  {
1048          struct STATFS_T stat_fs;          struct STATFS_T stat_fs;
1049          struct fileinfo *pfinfo;          struct fileinfo *pfinfo;
# Line 809  disk_query_volume_information(HANDLE han Line 1108  disk_query_volume_information(HANDLE han
1108  }  }
1109    
1110  NTSTATUS  NTSTATUS
1111  disk_query_directory(HANDLE handle, uint32 info_class, char *pattern, STREAM out)  disk_query_directory(NTHANDLE handle, uint32 info_class, char *pattern, STREAM out)
1112  {  {
1113          uint32 file_attributes, ft_low, ft_high;          uint32 file_attributes, ft_low, ft_high;
1114          char *dirname, fullpath[256];          char *dirname, fullpath[256];
# Line 827  disk_query_directory(HANDLE handle, uint Line 1126  disk_query_directory(HANDLE handle, uint
1126          {          {
1127                  case FileBothDirectoryInformation:                  case FileBothDirectoryInformation:
1128    
1129                          // If a search pattern is received, remember this pattern, and restart search                          /* If a search pattern is received, remember this pattern, and restart search */
1130                          if (pattern[0] != 0)                          if (pattern[0] != 0)
1131                          {                          {
1132                                  strncpy(pfinfo->pattern, 1 + strrchr(pattern, '/'), 64);                                  strncpy(pfinfo->pattern, 1 + strrchr(pattern, '/'), 64);
1133                                  rewinddir(pdir);                                  rewinddir(pdir);
1134                          }                          }
1135    
1136                          // find next dirent matching pattern                          /* find next dirent matching pattern */
1137                          pdirent = readdir(pdir);                          pdirent = readdir(pdir);
1138                          while (pdirent && fnmatch(pfinfo->pattern, pdirent->d_name, 0) != 0)                          while (pdirent && fnmatch(pfinfo->pattern, pdirent->d_name, 0) != 0)
1139                                  pdirent = readdir(pdir);                                  pdirent = readdir(pdir);
# Line 842  disk_query_directory(HANDLE handle, uint Line 1141  disk_query_directory(HANDLE handle, uint
1141                          if (pdirent == NULL)                          if (pdirent == NULL)
1142                                  return STATUS_NO_MORE_FILES;                                  return STATUS_NO_MORE_FILES;
1143    
1144                          // Get information for directory entry                          /* Get information for directory entry */
1145                          sprintf(fullpath, "%s/%s", dirname, pdirent->d_name);                          sprintf(fullpath, "%s/%s", dirname, pdirent->d_name);
1146    
1147                          if (stat(fullpath, &fstat))                          if (stat(fullpath, &fstat))
# Line 873  disk_query_directory(HANDLE handle, uint Line 1172  disk_query_directory(HANDLE handle, uint
1172                          if (!(fstat.st_mode & S_IWUSR))                          if (!(fstat.st_mode & S_IWUSR))
1173                                  file_attributes |= FILE_ATTRIBUTE_READONLY;                                  file_attributes |= FILE_ATTRIBUTE_READONLY;
1174    
1175                          // Return requested information                          /* Return requested information */
1176                          out_uint8s(out, 8);     //unknown zero                          out_uint8s(out, 8);     /* unknown zero */
1177    
1178                          seconds_since_1970_to_filetime(get_create_time(&fstat), &ft_high, &ft_low);                          seconds_since_1970_to_filetime(get_create_time(&fstat), &ft_high, &ft_low);
1179                          out_uint32_le(out, ft_low);     // create time                          out_uint32_le(out, ft_low);     /* create time */
1180                          out_uint32_le(out, ft_high);                          out_uint32_le(out, ft_high);
1181    
1182                          seconds_since_1970_to_filetime(fstat.st_atime, &ft_high, &ft_low);                          seconds_since_1970_to_filetime(fstat.st_atime, &ft_high, &ft_low);
1183                          out_uint32_le(out, ft_low);     //last_access_time                          out_uint32_le(out, ft_low);     /* last_access_time */
1184                          out_uint32_le(out, ft_high);                          out_uint32_le(out, ft_high);
1185    
1186                          seconds_since_1970_to_filetime(fstat.st_mtime, &ft_high, &ft_low);                          seconds_since_1970_to_filetime(fstat.st_mtime, &ft_high, &ft_low);
1187                          out_uint32_le(out, ft_low);     //last_write_time                          out_uint32_le(out, ft_low);     /* last_write_time */
1188                          out_uint32_le(out, ft_high);                          out_uint32_le(out, ft_high);
1189    
1190                          seconds_since_1970_to_filetime(fstat.st_ctime, &ft_high, &ft_low);                          seconds_since_1970_to_filetime(fstat.st_ctime, &ft_high, &ft_low);
1191                          out_uint32_le(out, ft_low);     //change_write_time                          out_uint32_le(out, ft_low);     /* change_write_time */
1192                          out_uint32_le(out, ft_high);                          out_uint32_le(out, ft_high);
1193    
1194                          out_uint32_le(out, fstat.st_size);      //filesize low                          out_uint32_le(out, fstat.st_size);      /* filesize low */
1195                          out_uint32_le(out, 0);  //filesize high                          out_uint32_le(out, 0);  /* filesize high */
1196                          out_uint32_le(out, fstat.st_size);      //filesize low                          out_uint32_le(out, fstat.st_size);      /* filesize low */
1197                          out_uint32_le(out, 0);  //filesize high                          out_uint32_le(out, 0);  /* filesize high */
1198                          out_uint32_le(out, file_attributes);                          out_uint32_le(out, file_attributes);
1199                          out_uint8(out, 2 * strlen(pdirent->d_name) + 2);        //unicode length                          out_uint8(out, 2 * strlen(pdirent->d_name) + 2);        /* unicode length */
1200                          out_uint8s(out, 7);     //pad?                          out_uint8s(out, 7);     /* pad? */
1201                          out_uint8(out, 0);      //8.3 file length                          out_uint8(out, 0);      /* 8.3 file length */
1202                          out_uint8s(out, 2 * 12);        //8.3 unicode length                          out_uint8s(out, 2 * 12);        /* 8.3 unicode length */
1203                          rdp_out_unistr(out, pdirent->d_name, 2 * strlen(pdirent->d_name));                          rdp_out_unistr(out, pdirent->d_name, 2 * strlen(pdirent->d_name));
1204                          break;                          break;
1205    
# Line 919  disk_query_directory(HANDLE handle, uint Line 1218  disk_query_directory(HANDLE handle, uint
1218    
1219    
1220  static NTSTATUS  static NTSTATUS
1221  disk_device_control(HANDLE handle, uint32 request, STREAM in, STREAM out)  disk_device_control(NTHANDLE handle, uint32 request, STREAM in, STREAM out)
1222  {  {
         uint32 result;  
   
1223          if (((request >> 16) != 20) || ((request >> 16) != 9))          if (((request >> 16) != 20) || ((request >> 16) != 9))
1224                  return STATUS_INVALID_PARAMETER;                  return STATUS_INVALID_PARAMETER;
1225    
# Line 934  disk_device_control(HANDLE handle, uint3 Line 1231  disk_device_control(HANDLE handle, uint3
1231    
1232          switch (request)          switch (request)
1233          {          {
1234                  case 25:        // ?                  case 25:        /* ? */
1235                  case 42:        // ?                  case 42:        /* ? */
1236                  default:                  default:
1237                          unimpl("DISK IOCTL %d\n", request);                          unimpl("DISK IOCTL %d\n", request);
1238                          return STATUS_INVALID_PARAMETER;                          return STATUS_INVALID_PARAMETER;

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

  ViewVC Help
Powered by ViewVC 1.1.26