/[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 661 by astrand, Fri Apr 16 13:03:13 2004 UTC revision 873 by stargo, Sat Apr 2 17:31:27 2005 UTC
# Line 20  Line 20 
20    
21  #include "disk.h"  #include "disk.h"
22    
 #if (defined(sun) && (defined(__svr4__) || defined(__SVR4)))  
 #define SOLARIS  
 #endif  
   
 #if (defined(SOLARIS) || defined(__hpux))  
 #define DIRFD(a) ((a)->dd_fd)  
 #else  
 #define DIRFD(a) (dirfd(a))  
 #endif  
   
23  #include <sys/types.h>  #include <sys/types.h>
24  #include <sys/stat.h>  #include <sys/stat.h>
25  #include <unistd.h>  #include <unistd.h>
# Line 41  Line 31 
31  #include <utime.h>  #include <utime.h>
32  #include <time.h>               /* ctime */  #include <time.h>               /* ctime */
33    
34    #if (defined(HAVE_DIRFD) || (HAVE_DECL_DIRFD == 1))
35    #define DIRFD(a) (dirfd(a))
36    #else
37    #define DIRFD(a) ((a)->DIR_FD_MEMBER_NAME)
38    #endif
39    
40  #if (defined(SOLARIS) || defined (__hpux) || defined(__BEOS__))  /* TODO: Fix mntent-handling for solaris
41  #include <sys/statvfs.h>        /* solaris statvfs */   * #include <sys/mntent.h> */
42  #include <sys/mntent.h>  #if (defined(HAVE_MNTENT_H) && defined(HAVE_SETMNTENT))
43  /* TODO: Fix mntent-handling for solaris */  #include <mntent.h>
44  #undef HAVE_MNTENT_H  #define MNTENT_PATH "/etc/mtab"
45  #define MNTENT_PATH "/etc/mnttab"  #define USE_SETMNTENT
46  #define STATFS_FN(path, buf) (statvfs(path,buf))  #endif
47  #define STATFS_T statvfs  
48  #define F_NAMELEN(buf) ((buf).f_namemax)  #ifdef HAVE_SYS_VFS_H
49    #include <sys/vfs.h>
50    #endif
51    
52    #ifdef HAVE_SYS_STATVFS_H
53    #include <sys/statvfs.h>
54    #endif
55    
56    #ifdef HAVE_SYS_STATFS_H
57    #include <sys/statfs.h>
58    #endif
59    
60  #elif (defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__))  #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  #else  #ifdef STAT_STATVFS
77  #include <sys/vfs.h>            /* linux statfs */  #define STATFS_FN(path, buf) (statvfs(path,buf))
78  #include <mntent.h>  #define STATFS_T statvfs
79  #define HAVE_MNTENT_H  #define USE_STATVFS
80  #define MNTENT_PATH "/etc/mtab"  #endif
81    
82    #ifdef STAT_STATVFS64
83    #define STATFS_FN(path, buf) (statvfs64(path,buf))
84    #define STATFS_T statvfs64
85    #define USE_STATVFS
86    #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 = 1;
117            long f_bsize = 512;
118            long f_blocks = 1;
119    };
120    #define STATFS_T dummy_statfs_t
121    #define STATFS_FN(path,buf) 0
122    #endif
123    
124  extern RDPDR_DEVICE g_rdpdr_device[];  extern RDPDR_DEVICE g_rdpdr_device[];
125    
126  FILEINFO g_fileinfo[MAX_OPEN_FILES];  FILEINFO g_fileinfo[MAX_OPEN_FILES];
127    BOOL g_notify_stamp = False;
128    
129  typedef struct  typedef struct
130  {  {
# Line 83  typedef struct Line 134  typedef struct
134          char type[256];          char type[256];
135  } FsInfoType;  } FsInfoType;
136    
137    static NTSTATUS NotifyInfo(NTHANDLE handle, uint32 info_class, NOTIFY * p);
138    
139  time_t  static time_t
140  get_create_time(struct stat *st)  get_create_time(struct stat *st)
141  {  {
142          time_t ret, ret1;          time_t ret, ret1;
# Line 99  get_create_time(struct stat *st) Line 151  get_create_time(struct stat *st)
151  }  }
152    
153  /* Convert seconds since 1970 to a filetime */  /* Convert seconds since 1970 to a filetime */
154  void  static void
155  seconds_since_1970_to_filetime(time_t seconds, uint32 * high, uint32 * low)  seconds_since_1970_to_filetime(time_t seconds, uint32 * high, uint32 * low)
156  {  {
157          unsigned long long ticks;          unsigned long long ticks;
# Line 110  seconds_since_1970_to_filetime(time_t se Line 162  seconds_since_1970_to_filetime(time_t se
162  }  }
163    
164  /* Convert seconds since 1970 back to filetime */  /* Convert seconds since 1970 back to filetime */
165  time_t  static time_t
166  convert_1970_to_filetime(uint32 high, uint32 low)  convert_1970_to_filetime(uint32 high, uint32 low)
167  {  {
168          unsigned long long ticks;          unsigned long long ticks;
# Line 125  convert_1970_to_filetime(uint32 high, ui Line 177  convert_1970_to_filetime(uint32 high, ui
177    
178  }  }
179    
180    /* A wrapper for ftruncate which supports growing files, even if the
181       native ftruncate doesn't. This is needed on Linux FAT filesystems,
182       for example. */
183    static int
184    ftruncate_growable(int fd, off_t length)
185    {
186            int ret;
187            off_t pos;
188            static const char zero;
189    
190            /* Try the simple method first */
191            if ((ret = ftruncate(fd, length)) != -1)
192            {
193                    return ret;
194            }
195    
196            /*
197             * Some kind of error. Perhaps we were trying to grow. Retry
198             * in a safe way.
199             */
200    
201            /* Get current position */
202            if ((pos = lseek(fd, 0, SEEK_CUR)) == -1)
203            {
204                    perror("lseek");
205                    return -1;
206            }
207    
208            /* Seek to new size */
209            if (lseek(fd, length, SEEK_SET) == -1)
210            {
211                    perror("lseek");
212                    return -1;
213            }
214    
215            /* Write a zero */
216            if (write(fd, &zero, 1) == -1)
217            {
218                    perror("write");
219                    return -1;
220            }
221    
222            /* Truncate. This shouldn't fail. */
223            if (ftruncate(fd, length) == -1)
224            {
225                    perror("ftruncate");
226                    return -1;
227            }
228    
229            /* Restore position */
230            if (lseek(fd, pos, SEEK_SET) == -1)
231            {
232                    perror("lseek");
233                    return -1;
234            }
235    
236            return 0;
237    }
238    
239    /* Just like open(2), but if a open with O_EXCL fails, retry with
240       GUARDED semantics. This might be necessary because some filesystems
241       (such as NFS filesystems mounted from a unfsd server) doesn't
242       support O_EXCL. GUARDED semantics are subject to race conditions,
243       but we can live with that.
244    */
245    static int
246    open_weak_exclusive(const char *pathname, int flags, mode_t mode)
247    {
248            int ret;
249            struct stat statbuf;
250    
251            ret = open(pathname, flags, mode);
252            if (ret != -1 || !(flags & O_EXCL))
253            {
254                    /* Success, or not using O_EXCL */
255                    return ret;
256            }
257    
258            /* An error occured, and we are using O_EXCL. In case the FS
259               doesn't support O_EXCL, some kind of error will be
260               returned. Unfortunately, we don't know which one. Linux
261               2.6.8 seems to return 524, but I cannot find a documented
262               #define for this case. So, we'll return only on errors that
263               we know aren't related to O_EXCL. */
264            switch (errno)
265            {
266                    case EACCES:
267                    case EEXIST:
268                    case EINTR:
269                    case EISDIR:
270                    case ELOOP:
271                    case ENAMETOOLONG:
272                    case ENOENT:
273                    case ENOTDIR:
274                            return ret;
275            }
276    
277            /* Retry with GUARDED semantics */
278            if (stat(pathname, &statbuf) != -1)
279            {
280                    /* File exists */
281                    errno = EEXIST;
282                    return -1;
283            }
284            else
285            {
286                    return open(pathname, flags & ~O_EXCL, mode);
287            }
288    }
289    
290  /* Enumeration of devices from rdesktop.c        */  /* Enumeration of devices from rdesktop.c        */
291  /* returns numer of units found and initialized. */  /* returns numer of units found and initialized. */
# Line 137  disk_enum_devices(uint32 * id, char *opt Line 298  disk_enum_devices(uint32 * id, char *opt
298          char *pos2;          char *pos2;
299          int count = 0;          int count = 0;
300    
301          // skip the first colon          /* skip the first colon */
302          optarg++;          optarg++;
303          while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)          while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
304          {          {
305                  pos2 = next_arg(optarg, '=');                  pos2 = next_arg(optarg, '=');
                 strcpy(g_rdpdr_device[*id].name, optarg);  
306    
307                  toupper_str(g_rdpdr_device[*id].name);                  strncpy(g_rdpdr_device[*id].name, optarg, sizeof(g_rdpdr_device[*id].name) - 1);
308                    if (strlen(optarg) > (sizeof(g_rdpdr_device[*id].name) - 1))
309                  /* add trailing colon to name. */                          fprintf(stderr, "share name %s truncated to %s\n", optarg,
310                  strcat(g_rdpdr_device[*id].name, ":");                                  g_rdpdr_device[*id].name);
311    
312                  g_rdpdr_device[*id].local_path = xmalloc(strlen(pos2) + 1);                  g_rdpdr_device[*id].local_path = xmalloc(strlen(pos2) + 1);
313                  strcpy(g_rdpdr_device[*id].local_path, pos2);                  strcpy(g_rdpdr_device[*id].local_path, pos2);
                 printf("DISK %s to %s\n", g_rdpdr_device[*id].name, g_rdpdr_device[*id].local_path);  
314                  g_rdpdr_device[*id].device_type = DEVICE_TYPE_DISK;                  g_rdpdr_device[*id].device_type = DEVICE_TYPE_DISK;
315                  count++;                  count++;
316                  (*id)++;                  (*id)++;
# Line 162  disk_enum_devices(uint32 * id, char *opt Line 321  disk_enum_devices(uint32 * id, char *opt
321  }  }
322    
323  /* Opens or creates a file or directory */  /* Opens or creates a file or directory */
324  NTSTATUS  static NTSTATUS
325  disk_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition,  disk_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition,
326              uint32 flags_and_attributes, char *filename, HANDLE * phandle)              uint32 flags_and_attributes, char *filename, NTHANDLE * phandle)
327  {  {
328          HANDLE handle;          NTHANDLE handle;
329          DIR *dirp;          DIR *dirp;
330          int flags, mode;          int flags, mode;
331          char path[256];          char path[256];
# Line 177  disk_create(uint32 device_id, uint32 acc Line 336  disk_create(uint32 device_id, uint32 acc
336          flags = 0;          flags = 0;
337          mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;          mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
338    
339            if (*filename && filename[strlen(filename) - 1] == '/')
         if (filename[strlen(filename) - 1] == '/')  
340                  filename[strlen(filename) - 1] = 0;                  filename[strlen(filename) - 1] = 0;
341          sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename);          sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename);
342    
# Line 186  disk_create(uint32 device_id, uint32 acc Line 344  disk_create(uint32 device_id, uint32 acc
344          {          {
345                  case CREATE_ALWAYS:                  case CREATE_ALWAYS:
346    
347                          // Delete existing file/link.                          /* Delete existing file/link. */
348                          unlink(path);                          unlink(path);
349                          flags |= O_CREAT;                          flags |= O_CREAT;
350                          break;                          break;
351    
352                  case CREATE_NEW:                  case CREATE_NEW:
353    
354                          // If the file already exists, then fail.                          /* If the file already exists, then fail. */
355                          flags |= O_CREAT | O_EXCL;                          flags |= O_CREAT | O_EXCL;
356                          break;                          break;
357    
358                  case OPEN_ALWAYS:                  case OPEN_ALWAYS:
359    
360                          // Create if not already exists.                          /* Create if not already exists. */
361                          flags |= O_CREAT;                          flags |= O_CREAT;
362                          break;                          break;
363    
364                  case OPEN_EXISTING:                  case OPEN_EXISTING:
365    
366                          // Default behaviour                          /* Default behaviour */
367                          break;                          break;
368    
369                  case TRUNCATE_EXISTING:                  case TRUNCATE_EXISTING:
370    
371                          // If the file does not exist, then fail.                          /* If the file does not exist, then fail. */
372                          flags |= O_TRUNC;                          flags |= O_TRUNC;
373                          break;                          break;
374          }          }
375    
376          //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); */
377    
378          // Get information about file and set that flag ourselfs          /* Get information about file and set that flag ourselfs */
379          if ((stat(path, &filestat) == 0) && (S_ISDIR(filestat.st_mode)))          if ((stat(path, &filestat) == 0) && (S_ISDIR(filestat.st_mode)))
380          {          {
381                  if (flags_and_attributes & FILE_NON_DIRECTORY_FILE)                  if (flags_and_attributes & FILE_NON_DIRECTORY_FILE)
# Line 271  disk_create(uint32 device_id, uint32 acc Line 429  disk_create(uint32 device_id, uint32 acc
429                          flags |= O_RDONLY;                          flags |= O_RDONLY;
430                  }                  }
431    
432                  handle = open(path, flags, mode);                  handle = open_weak_exclusive(path, flags, mode);
433                  if (handle == -1)                  if (handle == -1)
434                  {                  {
435                          switch (errno)                          switch (errno)
# Line 311  disk_create(uint32 device_id, uint32 acc Line 469  disk_create(uint32 device_id, uint32 acc
469    
470          if (dirp)          if (dirp)
471                  g_fileinfo[handle].pdir = dirp;                  g_fileinfo[handle].pdir = dirp;
472            else
473                    g_fileinfo[handle].pdir = NULL;
474    
475          g_fileinfo[handle].device_id = device_id;          g_fileinfo[handle].device_id = device_id;
476          g_fileinfo[handle].flags_and_attributes = flags_and_attributes;          g_fileinfo[handle].flags_and_attributes = flags_and_attributes;
477            g_fileinfo[handle].accessmask = accessmask;
478          strncpy(g_fileinfo[handle].path, path, 255);          strncpy(g_fileinfo[handle].path, path, 255);
479            g_fileinfo[handle].delete_on_close = False;
480            g_notify_stamp = True;
481    
482          *phandle = handle;          *phandle = handle;
483          return STATUS_SUCCESS;          return STATUS_SUCCESS;
484  }  }
485    
486  NTSTATUS  static NTSTATUS
487  disk_close(HANDLE handle)  disk_close(NTHANDLE handle)
488  {  {
489          struct fileinfo *pfinfo;          struct fileinfo *pfinfo;
490    
491          pfinfo = &(g_fileinfo[handle]);          pfinfo = &(g_fileinfo[handle]);
492    
493          if (pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE)          g_notify_stamp = True;
494    
495            rdpdr_abort_io(handle, 0, STATUS_CANCELLED);
496    
497            if (pfinfo->pdir)
498          {          {
499                  closedir(pfinfo->pdir);                  if (closedir(pfinfo->pdir) < 0)
500                  //FIXME: Should check exit code                  {
501                            perror("closedir");
502                            return STATUS_INVALID_HANDLE;
503                    }
504    
505                    if (pfinfo->delete_on_close)
506                            if (rmdir(pfinfo->path) < 0)
507                            {
508                                    perror(pfinfo->path);
509                                    return STATUS_ACCESS_DENIED;
510                            }
511                    pfinfo->delete_on_close = False;
512          }          }
513          else          else
514          {          {
515                  close(handle);                  if (close(handle) < 0)
516                    {
517                            perror("close");
518                            return STATUS_INVALID_HANDLE;
519                    }
520                    if (pfinfo->delete_on_close)
521                            if (unlink(pfinfo->path) < 0)
522                            {
523                                    perror(pfinfo->path);
524                                    return STATUS_ACCESS_DENIED;
525                            }
526    
527                    pfinfo->delete_on_close = False;
528          }          }
529    
530          return STATUS_SUCCESS;          return STATUS_SUCCESS;
531  }  }
532    
533  NTSTATUS  static NTSTATUS
534  disk_read(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)  disk_read(NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
535  {  {
536          int n;          int n;
537    
# Line 364  disk_read(HANDLE handle, uint8 * data, u Line 555  disk_read(HANDLE handle, uint8 * data, u
555                  switch (errno)                  switch (errno)
556                  {                  {
557                          case EISDIR:                          case EISDIR:
558                                  return STATUS_FILE_IS_A_DIRECTORY;                                  /* Implement 24 Byte directory read ??
559                                       with STATUS_NOT_IMPLEMENTED server doesn't read again */
560                                    /* return STATUS_FILE_IS_A_DIRECTORY; */
561                                    return STATUS_NOT_IMPLEMENTED;
562                          default:                          default:
563                                  perror("read");                                  perror("read");
564                                  return STATUS_INVALID_PARAMETER;                                  return STATUS_INVALID_PARAMETER;
# Line 376  disk_read(HANDLE handle, uint8 * data, u Line 570  disk_read(HANDLE handle, uint8 * data, u
570          return STATUS_SUCCESS;          return STATUS_SUCCESS;
571  }  }
572    
573  NTSTATUS  static NTSTATUS
574  disk_write(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)  disk_write(NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
575  {  {
576          int n;          int n;
577    
# Line 404  disk_write(HANDLE handle, uint8 * data, Line 598  disk_write(HANDLE handle, uint8 * data,
598  }  }
599    
600  NTSTATUS  NTSTATUS
601  disk_query_information(HANDLE handle, uint32 info_class, STREAM out)  disk_query_information(NTHANDLE handle, uint32 info_class, STREAM out)
602  {  {
603          uint32 file_attributes, ft_high, ft_low;          uint32 file_attributes, ft_high, ft_low;
604          struct stat filestat;          struct stat filestat;
# Line 412  disk_query_information(HANDLE handle, ui Line 606  disk_query_information(HANDLE handle, ui
606    
607          path = g_fileinfo[handle].path;          path = g_fileinfo[handle].path;
608    
609          // Get information about file          /* Get information about file */
610          if (fstat(handle, &filestat) != 0)          if (fstat(handle, &filestat) != 0)
611          {          {
612                  perror("stat");                  perror("stat");
# Line 420  disk_query_information(HANDLE handle, ui Line 614  disk_query_information(HANDLE handle, ui
614                  return STATUS_ACCESS_DENIED;                  return STATUS_ACCESS_DENIED;
615          }          }
616    
617          // Set file attributes          /* Set file attributes */
618          file_attributes = 0;          file_attributes = 0;
619          if (S_ISDIR(filestat.st_mode))          if (S_ISDIR(filestat.st_mode))
620                  file_attributes |= FILE_ATTRIBUTE_DIRECTORY;                  file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
# Line 435  disk_query_information(HANDLE handle, ui Line 629  disk_query_information(HANDLE handle, ui
629          if (!(filestat.st_mode & S_IWUSR))          if (!(filestat.st_mode & S_IWUSR))
630                  file_attributes |= FILE_ATTRIBUTE_READONLY;                  file_attributes |= FILE_ATTRIBUTE_READONLY;
631    
632          // Return requested data          /* Return requested data */
633          switch (info_class)          switch (info_class)
634          {          {
635                  case FileBasicInformation:                  case FileBasicInformation:
636                          seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high,                          seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high,
637                                                         &ft_low);                                                         &ft_low);
638                          out_uint32_le(out, ft_low);     //create_access_time                          out_uint32_le(out, ft_low);     /* create_access_time */
639                          out_uint32_le(out, ft_high);                          out_uint32_le(out, ft_high);
640    
641                          seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low);                          seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low);
642                          out_uint32_le(out, ft_low);     //last_access_time                          out_uint32_le(out, ft_low);     /* last_access_time */
643                          out_uint32_le(out, ft_high);                          out_uint32_le(out, ft_high);
644    
645                          seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low);                          seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low);
646                          out_uint32_le(out, ft_low);     //last_write_time                          out_uint32_le(out, ft_low);     /* last_write_time */
647                          out_uint32_le(out, ft_high);                          out_uint32_le(out, ft_high);
648    
649                          seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low);                          seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low);
650                          out_uint32_le(out, ft_low);     //last_change_time                          out_uint32_le(out, ft_low);     /* last_change_time */
651                          out_uint32_le(out, ft_high);                          out_uint32_le(out, ft_high);
652    
653                          out_uint32_le(out, file_attributes);                          out_uint32_le(out, file_attributes);
# Line 461  disk_query_information(HANDLE handle, ui Line 655  disk_query_information(HANDLE handle, ui
655    
656                  case FileStandardInformation:                  case FileStandardInformation:
657    
658                          out_uint32_le(out, filestat.st_size);   //Allocation size                          out_uint32_le(out, filestat.st_size);   /* Allocation size */
659                          out_uint32_le(out, 0);                          out_uint32_le(out, 0);
660                          out_uint32_le(out, filestat.st_size);   //End of file                          out_uint32_le(out, filestat.st_size);   /* End of file */
661                          out_uint32_le(out, 0);                          out_uint32_le(out, 0);
662                          out_uint32_le(out, filestat.st_nlink);  //Number of links                          out_uint32_le(out, filestat.st_nlink);  /* Number of links */
663                          out_uint8(out, 0);      //Delete pending                          out_uint8(out, 0);      /* Delete pending */
664                          out_uint8(out, S_ISDIR(filestat.st_mode) ? 1 : 0);      //Directory                          out_uint8(out, S_ISDIR(filestat.st_mode) ? 1 : 0);      /* Directory */
665                          break;                          break;
666    
667                  case FileObjectIdInformation:                  case FileObjectIdInformation:
# Line 485  disk_query_information(HANDLE handle, ui Line 679  disk_query_information(HANDLE handle, ui
679  }  }
680    
681  NTSTATUS  NTSTATUS
682  disk_set_information(HANDLE handle, uint32 info_class, STREAM in, STREAM out)  disk_set_information(NTHANDLE handle, uint32 info_class, STREAM in, STREAM out)
683  {  {
684          uint32 device_id, length, file_attributes, ft_high, ft_low;          uint32 length, file_attributes, ft_high, ft_low, delete_on_close;
685          char newname[256], fullpath[256];          char newname[256], fullpath[256];
686          struct fileinfo *pfinfo;          struct fileinfo *pfinfo;
   
687          int mode;          int mode;
688          struct stat filestat;          struct stat filestat;
689          time_t write_time, change_time, access_time, mod_time;          time_t write_time, change_time, access_time, mod_time;
# Line 498  disk_set_information(HANDLE handle, uint Line 691  disk_set_information(HANDLE handle, uint
691          struct STATFS_T stat_fs;          struct STATFS_T stat_fs;
692    
693          pfinfo = &(g_fileinfo[handle]);          pfinfo = &(g_fileinfo[handle]);
694            g_notify_stamp = True;
695    
696          switch (info_class)          switch (info_class)
697          {          {
# Line 507  disk_set_information(HANDLE handle, uint Line 701  disk_set_information(HANDLE handle, uint
701                          in_uint8s(in, 4);       /* Handle of root dir? */                          in_uint8s(in, 4);       /* Handle of root dir? */
702                          in_uint8s(in, 24);      /* unknown */                          in_uint8s(in, 24);      /* unknown */
703    
704                          // CreationTime                          /* CreationTime */
705                          in_uint32_le(in, ft_low);                          in_uint32_le(in, ft_low);
706                          in_uint32_le(in, ft_high);                          in_uint32_le(in, ft_high);
707    
708                          // AccessTime                          /* AccessTime */
709                          in_uint32_le(in, ft_low);                          in_uint32_le(in, ft_low);
710                          in_uint32_le(in, ft_high);                          in_uint32_le(in, ft_high);
711                          if (ft_low || ft_high)                          if (ft_low || ft_high)
712                                  access_time = convert_1970_to_filetime(ft_high, ft_low);                                  access_time = convert_1970_to_filetime(ft_high, ft_low);
713    
714                          // WriteTime                          /* WriteTime */
715                          in_uint32_le(in, ft_low);                          in_uint32_le(in, ft_low);
716                          in_uint32_le(in, ft_high);                          in_uint32_le(in, ft_high);
717                          if (ft_low || ft_high)                          if (ft_low || ft_high)
718                                  write_time = convert_1970_to_filetime(ft_high, ft_low);                                  write_time = convert_1970_to_filetime(ft_high, ft_low);
719    
720                          // ChangeTime                          /* ChangeTime */
721                          in_uint32_le(in, ft_low);                          in_uint32_le(in, ft_low);
722                          in_uint32_le(in, ft_high);                          in_uint32_le(in, ft_high);
723                          if (ft_low || ft_high)                          if (ft_low || ft_high)
# Line 557  disk_set_information(HANDLE handle, uint Line 751  disk_set_information(HANDLE handle, uint
751                                  printf("FileBasicInformation modification time %s",                                  printf("FileBasicInformation modification time %s",
752                                         ctime(&tvs.modtime));                                         ctime(&tvs.modtime));
753  #endif  #endif
754                                  if (utime(pfinfo->path, &tvs))                                  if (utime(pfinfo->path, &tvs) && errno != EPERM)
755                                          return STATUS_ACCESS_DENIED;                                          return STATUS_ACCESS_DENIED;
756                          }                          }
757    
758                          if (!file_attributes)                          if (!file_attributes)
759                                  break;  // not valid                                  break;  /* not valid */
760    
761                          mode = filestat.st_mode;                          mode = filestat.st_mode;
762    
# Line 615  disk_set_information(HANDLE handle, uint Line 809  disk_set_information(HANDLE handle, uint
809                             FileDispositionInformation requests with                             FileDispositionInformation requests with
810                             DeleteFile set to FALSE should unschedule                             DeleteFile set to FALSE should unschedule
811                             the delete. See                             the delete. See
812                             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);  
813    
814                          /* 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);  
815    
816                          if ((pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE))       // remove a directory                          if (delete_on_close ||
817                                (pfinfo->
818                                 accessmask & (FILE_DELETE_ON_CLOSE | FILE_COMPLETE_IF_OPLOCKED)))
819                          {                          {
820                                  if (rmdir(pfinfo->path) < 0)                                  pfinfo->delete_on_close = True;
                                         return STATUS_ACCESS_DENIED;  
821                          }                          }
                         else if (unlink(pfinfo->path) < 0)      // unlink a file  
                                 return STATUS_ACCESS_DENIED;  
822    
823                          break;                          break;
824    
# Line 650  disk_set_information(HANDLE handle, uint Line 835  disk_set_information(HANDLE handle, uint
835    
836                          /* prevents start of writing if not enough space left on device */                          /* prevents start of writing if not enough space left on device */
837                          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)
838                                  if (stat_fs.f_bsize * stat_fs.f_bfree < length)                                  if (stat_fs.f_bfree * stat_fs.f_bsize < length)
839                                          return STATUS_DISK_FULL;                                          return STATUS_DISK_FULL;
840    
841                          if (ftruncate(handle, length) != 0)                          if (ftruncate_growable(handle, length) != 0)
842                          {                          {
                                 perror("ftruncate");  
843                                  return STATUS_DISK_FULL;                                  return STATUS_DISK_FULL;
844                          }                          }
845    
# Line 668  disk_set_information(HANDLE handle, uint Line 852  disk_set_information(HANDLE handle, uint
852          return STATUS_SUCCESS;          return STATUS_SUCCESS;
853  }  }
854    
855  FsInfoType *  NTSTATUS
856    disk_check_notify(NTHANDLE handle)
857    {
858            struct fileinfo *pfinfo;
859            NTSTATUS status = STATUS_PENDING;
860    
861            NOTIFY notify;
862    
863            pfinfo = &(g_fileinfo[handle]);
864            if (!pfinfo->pdir)
865                    return STATUS_INVALID_DEVICE_REQUEST;
866    
867    
868    
869            status = NotifyInfo(handle, pfinfo->info_class, &notify);
870    
871            if (status != STATUS_PENDING)
872                    return status;
873    
874            if (memcmp(&pfinfo->notify, &notify, sizeof(NOTIFY)))
875            {
876                    /*printf("disk_check_notify found changed event\n"); */
877                    memcpy(&pfinfo->notify, &notify, sizeof(NOTIFY));
878                    status = STATUS_NOTIFY_ENUM_DIR;
879            }
880    
881            return status;
882    
883    
884    }
885    
886    NTSTATUS
887    disk_create_notify(NTHANDLE handle, uint32 info_class)
888    {
889    
890            struct fileinfo *pfinfo;
891            NTSTATUS ret = STATUS_PENDING;
892    
893            /* printf("start disk_create_notify info_class %X\n", info_class); */
894    
895            pfinfo = &(g_fileinfo[handle]);
896            pfinfo->info_class = info_class;
897    
898            ret = NotifyInfo(handle, info_class, &pfinfo->notify);
899    
900            if (info_class & 0x1000)
901            {                       /* ???? */
902                    if (ret == STATUS_PENDING)
903                            return STATUS_SUCCESS;
904            }
905    
906            /* printf("disk_create_notify: num_entries %d\n", pfinfo->notify.num_entries); */
907    
908    
909            return ret;
910    
911    }
912    
913    static NTSTATUS
914    NotifyInfo(NTHANDLE handle, uint32 info_class, NOTIFY * p)
915    {
916            struct fileinfo *pfinfo;
917            struct stat buf;
918            struct dirent *dp;
919            char *fullname;
920            DIR *dpr;
921    
922            pfinfo = &(g_fileinfo[handle]);
923            if (fstat(handle, &buf) < 0)
924            {
925                    perror("NotifyInfo");
926                    return STATUS_ACCESS_DENIED;
927            }
928            p->modify_time = buf.st_mtime;
929            p->status_time = buf.st_ctime;
930            p->num_entries = 0;
931            p->total_time = 0;
932    
933    
934            dpr = opendir(pfinfo->path);
935            if (!dpr)
936            {
937                    perror("NotifyInfo");
938                    return STATUS_ACCESS_DENIED;
939            }
940    
941    
942            while ((dp = readdir(dpr)))
943            {
944                    if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
945                            continue;
946                    p->num_entries++;
947                    fullname = xmalloc(strlen(pfinfo->path) + strlen(dp->d_name) + 2);
948                    sprintf(fullname, "%s/%s", pfinfo->path, dp->d_name);
949    
950                    if (!stat(fullname, &buf))
951                    {
952                            p->total_time += (buf.st_mtime + buf.st_ctime);
953                    }
954    
955                    xfree(fullname);
956            }
957            closedir(dpr);
958    
959            return STATUS_PENDING;
960    }
961    
962    static FsInfoType *
963  FsVolumeInfo(char *fpath)  FsVolumeInfo(char *fpath)
964  {  {
965    
966  #ifdef HAVE_MNTENT_H          static FsInfoType info;
967    #ifdef USE_SETMNTENT
968          FILE *fdfs;          FILE *fdfs;
969          struct mntent *e;          struct mntent *e;
970          static FsInfoType info;  #endif
971    
972          /* initialize */          /* initialize */
973          memset(&info, 0, sizeof(info));          memset(&info, 0, sizeof(info));
974          strcpy(info.label, "RDESKTOP");          strcpy(info.label, "RDESKTOP");
975          strcpy(info.type, "RDPFS");          strcpy(info.type, "RDPFS");
976    
977    #ifdef USE_SETMNTENT
978          fdfs = setmntent(MNTENT_PATH, "r");          fdfs = setmntent(MNTENT_PATH, "r");
979          if (!fdfs)          if (!fdfs)
980                  return &info;                  return &info;
# Line 715  FsVolumeInfo(char *fpath) Line 1008  FsVolumeInfo(char *fpath)
1008                                                  read(fd, buf, sizeof(buf));                                                  read(fd, buf, sizeof(buf));
1009                                                  strncpy(info.label, buf + 41, 32);                                                  strncpy(info.label, buf + 41, 32);
1010                                                  info.label[32] = '\0';                                                  info.label[32] = '\0';
1011                                                  //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]; */
1012                                          }                                          }
1013                                          close(fd);                                          close(fd);
1014                                  }                                  }
# Line 724  FsVolumeInfo(char *fpath) Line 1017  FsVolumeInfo(char *fpath)
1017          }          }
1018          endmntent(fdfs);          endmntent(fdfs);
1019  #else  #else
         static FsInfoType info;  
   
1020          /* initialize */          /* initialize */
1021          memset(&info, 0, sizeof(info));          memset(&info, 0, sizeof(info));
1022          strcpy(info.label, "RDESKTOP");          strcpy(info.label, "RDESKTOP");
# Line 737  FsVolumeInfo(char *fpath) Line 1028  FsVolumeInfo(char *fpath)
1028    
1029    
1030  NTSTATUS  NTSTATUS
1031  disk_query_volume_information(HANDLE handle, uint32 info_class, STREAM out)  disk_query_volume_information(NTHANDLE handle, uint32 info_class, STREAM out)
1032  {  {
1033          struct STATFS_T stat_fs;          struct STATFS_T stat_fs;
1034          struct fileinfo *pfinfo;          struct fileinfo *pfinfo;
# Line 802  disk_query_volume_information(HANDLE han Line 1093  disk_query_volume_information(HANDLE han
1093  }  }
1094    
1095  NTSTATUS  NTSTATUS
1096  disk_query_directory(HANDLE handle, uint32 info_class, char *pattern, STREAM out)  disk_query_directory(NTHANDLE handle, uint32 info_class, char *pattern, STREAM out)
1097  {  {
1098          uint32 file_attributes, ft_low, ft_high;          uint32 file_attributes, ft_low, ft_high;
1099          char *dirname, fullpath[256];          char *dirname, fullpath[256];
# Line 818  disk_query_directory(HANDLE handle, uint Line 1109  disk_query_directory(HANDLE handle, uint
1109    
1110          switch (info_class)          switch (info_class)
1111          {          {
1112                  case 3: //FIXME: Why 3?                  case FileBothDirectoryInformation:
1113    
1114                          // If a search pattern is received, remember this pattern, and restart search                          /* If a search pattern is received, remember this pattern, and restart search */
1115                          if (pattern[0] != 0)                          if (pattern[0] != 0)
1116                          {                          {
1117                                  strncpy(pfinfo->pattern, 1 + strrchr(pattern, '/'), 64);                                  strncpy(pfinfo->pattern, 1 + strrchr(pattern, '/'), 64);
1118                                  rewinddir(pdir);                                  rewinddir(pdir);
1119                          }                          }
1120    
1121                          // find next dirent matching pattern                          /* find next dirent matching pattern */
1122                          pdirent = readdir(pdir);                          pdirent = readdir(pdir);
1123                          while (pdirent && fnmatch(pfinfo->pattern, pdirent->d_name, 0) != 0)                          while (pdirent && fnmatch(pfinfo->pattern, pdirent->d_name, 0) != 0)
1124                                  pdirent = readdir(pdir);                                  pdirent = readdir(pdir);
# Line 835  disk_query_directory(HANDLE handle, uint Line 1126  disk_query_directory(HANDLE handle, uint
1126                          if (pdirent == NULL)                          if (pdirent == NULL)
1127                                  return STATUS_NO_MORE_FILES;                                  return STATUS_NO_MORE_FILES;
1128    
1129                          // Get information for directory entry                          /* Get information for directory entry */
1130                          sprintf(fullpath, "%s/%s", dirname, pdirent->d_name);                          sprintf(fullpath, "%s/%s", dirname, pdirent->d_name);
1131    
                         /* JIF  
                            printf("Stat: %s\n", fullpath); */  
1132                          if (stat(fullpath, &fstat))                          if (stat(fullpath, &fstat))
1133                          {                          {
1134                                  perror("stat");                                  switch (errno)
1135                                  out_uint8(out, 0);                                  {
1136                                  return STATUS_ACCESS_DENIED;                                          case ENOENT:
1137                                            case ELOOP:
1138                                            case EACCES:
1139                                                    /* These are non-fatal errors. */
1140                                                    memset(&fstat, 0, sizeof(fstat));
1141                                                    break;
1142                                            default:
1143                                                    /* Fatal error. By returning STATUS_NO_SUCH_FILE,
1144                                                       the directory list operation will be aborted */
1145                                                    perror(fullpath);
1146                                                    out_uint8(out, 0);
1147                                                    return STATUS_NO_SUCH_FILE;
1148                                    }
1149                          }                          }
1150    
1151                          if (S_ISDIR(fstat.st_mode))                          if (S_ISDIR(fstat.st_mode))
# Line 856  disk_query_directory(HANDLE handle, uint Line 1157  disk_query_directory(HANDLE handle, uint
1157                          if (!(fstat.st_mode & S_IWUSR))                          if (!(fstat.st_mode & S_IWUSR))
1158                                  file_attributes |= FILE_ATTRIBUTE_READONLY;                                  file_attributes |= FILE_ATTRIBUTE_READONLY;
1159    
1160                          // Return requested information                          /* Return requested information */
1161                          out_uint8s(out, 8);     //unknown zero                          out_uint8s(out, 8);     /* unknown zero */
1162    
1163                          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);
1164                          out_uint32_le(out, ft_low);     // create time                          out_uint32_le(out, ft_low);     /* create time */
1165                          out_uint32_le(out, ft_high);                          out_uint32_le(out, ft_high);
1166    
1167                          seconds_since_1970_to_filetime(fstat.st_atime, &ft_high, &ft_low);                          seconds_since_1970_to_filetime(fstat.st_atime, &ft_high, &ft_low);
1168                          out_uint32_le(out, ft_low);     //last_access_time                          out_uint32_le(out, ft_low);     /* last_access_time */
1169                          out_uint32_le(out, ft_high);                          out_uint32_le(out, ft_high);
1170    
1171                          seconds_since_1970_to_filetime(fstat.st_mtime, &ft_high, &ft_low);                          seconds_since_1970_to_filetime(fstat.st_mtime, &ft_high, &ft_low);
1172                          out_uint32_le(out, ft_low);     //last_write_time                          out_uint32_le(out, ft_low);     /* last_write_time */
1173                          out_uint32_le(out, ft_high);                          out_uint32_le(out, ft_high);
1174    
1175                          seconds_since_1970_to_filetime(fstat.st_ctime, &ft_high, &ft_low);                          seconds_since_1970_to_filetime(fstat.st_ctime, &ft_high, &ft_low);
1176                          out_uint32_le(out, ft_low);     //change_write_time                          out_uint32_le(out, ft_low);     /* change_write_time */
1177                          out_uint32_le(out, ft_high);                          out_uint32_le(out, ft_high);
1178    
1179                          out_uint32_le(out, fstat.st_size);      //filesize low                          out_uint32_le(out, fstat.st_size);      /* filesize low */
1180                          out_uint32_le(out, 0);  //filesize high                          out_uint32_le(out, 0);  /* filesize high */
1181                          out_uint32_le(out, fstat.st_size);      //filesize low                          out_uint32_le(out, fstat.st_size);      /* filesize low */
1182                          out_uint32_le(out, 0);  //filesize high                          out_uint32_le(out, 0);  /* filesize high */
1183                          out_uint32_le(out, file_attributes);                          out_uint32_le(out, file_attributes);
1184                          out_uint8(out, 2 * strlen(pdirent->d_name) + 2);        //unicode length                          out_uint8(out, 2 * strlen(pdirent->d_name) + 2);        /* unicode length */
1185                          out_uint8s(out, 7);     //pad?                          out_uint8s(out, 7);     /* pad? */
1186                          out_uint8(out, 0);      //8.3 file length                          out_uint8(out, 0);      /* 8.3 file length */
1187                          out_uint8s(out, 2 * 12);        //8.3 unicode length                          out_uint8s(out, 2 * 12);        /* 8.3 unicode length */
1188                          rdp_out_unistr(out, pdirent->d_name, 2 * strlen(pdirent->d_name));                          rdp_out_unistr(out, pdirent->d_name, 2 * strlen(pdirent->d_name));
1189                          break;                          break;
1190    
1191                  default:                  default:
1192                            /* FIXME: Support FileDirectoryInformation,
1193                               FileFullDirectoryInformation, and
1194                               FileNamesInformation */
1195    
1196                          unimpl("IRP Query Directory sub: 0x%x\n", info_class);                          unimpl("IRP Query Directory sub: 0x%x\n", info_class);
1197                          return STATUS_INVALID_PARAMETER;                          return STATUS_INVALID_PARAMETER;
# Line 899  disk_query_directory(HANDLE handle, uint Line 1203  disk_query_directory(HANDLE handle, uint
1203    
1204    
1205  static NTSTATUS  static NTSTATUS
1206  disk_device_control(HANDLE handle, uint32 request, STREAM in, STREAM out)  disk_device_control(NTHANDLE handle, uint32 request, STREAM in, STREAM out)
1207  {  {
         uint32 result;  
   
1208          if (((request >> 16) != 20) || ((request >> 16) != 9))          if (((request >> 16) != 20) || ((request >> 16) != 9))
1209                  return STATUS_INVALID_PARAMETER;                  return STATUS_INVALID_PARAMETER;
1210    
# Line 914  disk_device_control(HANDLE handle, uint3 Line 1216  disk_device_control(HANDLE handle, uint3
1216    
1217          switch (request)          switch (request)
1218          {          {
1219                  case 25:        // ?                  case 25:        /* ? */
1220                  case 42:        // ?                  case 42:        /* ? */
1221                  default:                  default:
1222                          unimpl("DISK IOCTL %d\n", request);                          unimpl("DISK IOCTL %d\n", request);
1223                          return STATUS_INVALID_PARAMETER;                          return STATUS_INVALID_PARAMETER;

Legend:
Removed from v.661  
changed lines
  Added in v.873

  ViewVC Help
Powered by ViewVC 1.1.26