/[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

Annotation of /jpeg/rdesktop/trunk/disk.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1010 - (hide annotations)
Wed Aug 31 13:00:57 2005 UTC (18 years, 8 months ago) by astrand
Original Path: sourceforge.net/trunk/rdesktop/disk.c
File MIME type: text/plain
File size: 28452 byte(s)
Using new utility function str_startswith, to get rid of many sizeof:s and hardcoded constants.

1 n-ki 569 /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.
3     Disk Redirection
4     Copyright (C) Jeroen Meijer 2003
5    
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10    
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     GNU General Public License for more details.
15    
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19     */
20    
21 astrand 652 #include "disk.h"
22 n-ki 569
23     #include <sys/types.h>
24     #include <sys/stat.h>
25     #include <unistd.h>
26     #include <fcntl.h> /* open, close */
27     #include <dirent.h> /* opendir, closedir, readdir */
28     #include <fnmatch.h>
29     #include <errno.h> /* errno */
30 stargo 902 #include <stdio.h>
31 stargo 572
32 n-ki 600 #include <utime.h>
33     #include <time.h> /* ctime */
34    
35 stargo 759 #if (defined(HAVE_DIRFD) || (HAVE_DECL_DIRFD == 1))
36 stargo 742 #define DIRFD(a) (dirfd(a))
37     #else
38     #define DIRFD(a) ((a)->DIR_FD_MEMBER_NAME)
39     #endif
40 n-ki 600
41 stargo 873 /* TODO: Fix mntent-handling for solaris
42     * #include <sys/mntent.h> */
43     #if (defined(HAVE_MNTENT_H) && defined(HAVE_SETMNTENT))
44     #include <mntent.h>
45     #define MNTENT_PATH "/etc/mtab"
46     #define USE_SETMNTENT
47 stargo 742 #endif
48    
49 stargo 873 #ifdef HAVE_SYS_VFS_H
50     #include <sys/vfs.h>
51     #endif
52 stargo 573
53 stargo 873 #ifdef HAVE_SYS_STATVFS_H
54     #include <sys/statvfs.h>
55     #endif
56    
57     #ifdef HAVE_SYS_STATFS_H
58     #include <sys/statfs.h>
59     #endif
60    
61     #ifdef HAVE_SYS_PARAM_H
62 stargo 573 #include <sys/param.h>
63 stargo 873 #endif
64    
65     #ifdef HAVE_SYS_MOUNT_H
66 stargo 573 #include <sys/mount.h>
67 stargo 873 #endif
68    
69     #include "rdesktop.h"
70    
71     #ifdef STAT_STATFS3_OSF1
72     #define STATFS_FN(path, buf) (statfs(path,buf,sizeof(buf)))
73 stargo 574 #define STATFS_T statfs
74 stargo 873 #define USE_STATFS
75     #endif
76 stargo 573
77 stargo 873 #ifdef STAT_STATVFS
78 stargo 745 #define STATFS_FN(path, buf) (statvfs(path,buf))
79     #define STATFS_T statvfs
80 stargo 873 #define USE_STATVFS
81     #endif
82 stargo 745
83 stargo 873 #ifdef STAT_STATVFS64
84     #define STATFS_FN(path, buf) (statvfs64(path,buf))
85     #define STATFS_T statvfs64
86     #define USE_STATVFS
87     #endif
88 stargo 807
89 stargo 873 #if (defined(STAT_STATFS2_FS_DATA) || defined(STAT_STATFS2_BSIZE) || defined(STAT_STATFS2_FSIZE))
90 stargo 574 #define STATFS_FN(path, buf) (statfs(path,buf))
91     #define STATFS_T statfs
92 stargo 873 #define USE_STATFS
93     #endif
94    
95     #ifdef STAT_STATFS4
96     #define STATFS_FN(path, buf) (statfs(path,buf,sizeof(buf),0))
97     #define STATFS_T statfs
98     #define USE_STATFS
99     #endif
100    
101     #if ((defined(USE_STATFS) && defined(HAVE_STRUCT_STATFS_F_NAMEMAX)) || (defined(USE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_NAMEMAX)))
102     #define F_NAMELEN(buf) ((buf).f_namemax)
103     #endif
104    
105     #if ((defined(USE_STATFS) && defined(HAVE_STRUCT_STATFS_F_NAMELEN)) || (defined(USE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_NAMELEN)))
106 stargo 573 #define F_NAMELEN(buf) ((buf).f_namelen)
107 stargo 572 #endif
108    
109 stargo 873 #ifndef F_NAMELEN
110     #define F_NAMELEN(buf) (255)
111     #endif
112    
113     /* Dummy statfs fallback */
114     #ifndef STATFS_T
115     struct dummy_statfs_t
116     {
117 stargo 875 long f_bfree;
118     long f_bsize;
119     long f_blocks;
120     int f_namelen;
121     int f_namemax;
122 stargo 873 };
123 stargo 875
124 astrand 943 static int
125 astrand 879 dummy_statfs(struct dummy_statfs_t *buf)
126 stargo 875 {
127 astrand 879 buf->f_blocks = 262144;
128     buf->f_bfree = 131072;
129     buf->f_bsize = 512;
130     buf->f_namelen = 255;
131     buf->f_namemax = 255;
132 stargo 875
133     return 0;
134     }
135    
136 stargo 873 #define STATFS_T dummy_statfs_t
137 stargo 875 #define STATFS_FN(path,buf) (dummy_statfs(buf))
138 stargo 873 #endif
139    
140 n-ki 569 extern RDPDR_DEVICE g_rdpdr_device[];
141    
142 n-ki 627 FILEINFO g_fileinfo[MAX_OPEN_FILES];
143 stargo 795 BOOL g_notify_stamp = False;
144 n-ki 569
145 n-ki 615 typedef struct
146     {
147 stargo 978 char name[PATH_MAX];
148     char label[PATH_MAX];
149 n-ki 615 unsigned long serial;
150 stargo 978 char type[PATH_MAX];
151 n-ki 615 } FsInfoType;
152    
153 stargo 795 static NTSTATUS NotifyInfo(NTHANDLE handle, uint32 info_class, NOTIFY * p);
154 n-ki 615
155 astrand 664 static time_t
156 n-ki 600 get_create_time(struct stat *st)
157     {
158     time_t ret, ret1;
159    
160     ret = MIN(st->st_ctime, st->st_mtime);
161     ret1 = MIN(ret, st->st_atime);
162    
163     if (ret1 != (time_t) 0)
164     return ret1;
165    
166     return ret;
167     }
168    
169 n-ki 569 /* Convert seconds since 1970 to a filetime */
170 astrand 664 static void
171 n-ki 569 seconds_since_1970_to_filetime(time_t seconds, uint32 * high, uint32 * low)
172     {
173     unsigned long long ticks;
174    
175     ticks = (seconds + 11644473600LL) * 10000000;
176     *low = (uint32) ticks;
177     *high = (uint32) (ticks >> 32);
178     }
179    
180 n-ki 600 /* Convert seconds since 1970 back to filetime */
181 astrand 664 static time_t
182 n-ki 600 convert_1970_to_filetime(uint32 high, uint32 low)
183     {
184     unsigned long long ticks;
185     time_t val;
186    
187     ticks = low + (((unsigned long long) high) << 32);
188     ticks /= 10000000;
189     ticks -= 11644473600LL;
190    
191     val = (time_t) ticks;
192     return (val);
193    
194     }
195    
196 astrand 785 /* A wrapper for ftruncate which supports growing files, even if the
197     native ftruncate doesn't. This is needed on Linux FAT filesystems,
198     for example. */
199     static int
200     ftruncate_growable(int fd, off_t length)
201     {
202     int ret;
203     off_t pos;
204     static const char zero;
205 n-ki 600
206 astrand 785 /* Try the simple method first */
207     if ((ret = ftruncate(fd, length)) != -1)
208     {
209     return ret;
210     }
211    
212     /*
213     * Some kind of error. Perhaps we were trying to grow. Retry
214     * in a safe way.
215     */
216    
217     /* Get current position */
218     if ((pos = lseek(fd, 0, SEEK_CUR)) == -1)
219     {
220     perror("lseek");
221     return -1;
222     }
223    
224     /* Seek to new size */
225     if (lseek(fd, length, SEEK_SET) == -1)
226     {
227     perror("lseek");
228     return -1;
229     }
230    
231     /* Write a zero */
232     if (write(fd, &zero, 1) == -1)
233     {
234     perror("write");
235     return -1;
236     }
237    
238     /* Truncate. This shouldn't fail. */
239     if (ftruncate(fd, length) == -1)
240     {
241     perror("ftruncate");
242     return -1;
243     }
244    
245     /* Restore position */
246     if (lseek(fd, pos, SEEK_SET) == -1)
247     {
248     perror("lseek");
249     return -1;
250     }
251    
252     return 0;
253     }
254    
255 astrand 790 /* Just like open(2), but if a open with O_EXCL fails, retry with
256     GUARDED semantics. This might be necessary because some filesystems
257     (such as NFS filesystems mounted from a unfsd server) doesn't
258     support O_EXCL. GUARDED semantics are subject to race conditions,
259     but we can live with that.
260     */
261     static int
262     open_weak_exclusive(const char *pathname, int flags, mode_t mode)
263     {
264     int ret;
265     struct stat statbuf;
266 astrand 785
267 astrand 790 ret = open(pathname, flags, mode);
268     if (ret != -1 || !(flags & O_EXCL))
269     {
270     /* Success, or not using O_EXCL */
271     return ret;
272     }
273    
274     /* An error occured, and we are using O_EXCL. In case the FS
275     doesn't support O_EXCL, some kind of error will be
276     returned. Unfortunately, we don't know which one. Linux
277     2.6.8 seems to return 524, but I cannot find a documented
278     #define for this case. So, we'll return only on errors that
279     we know aren't related to O_EXCL. */
280     switch (errno)
281     {
282     case EACCES:
283     case EEXIST:
284     case EINTR:
285     case EISDIR:
286     case ELOOP:
287     case ENAMETOOLONG:
288     case ENOENT:
289     case ENOTDIR:
290     return ret;
291     }
292    
293     /* Retry with GUARDED semantics */
294     if (stat(pathname, &statbuf) != -1)
295     {
296     /* File exists */
297     errno = EEXIST;
298     return -1;
299     }
300     else
301     {
302     return open(pathname, flags & ~O_EXCL, mode);
303     }
304     }
305    
306 n-ki 569 /* Enumeration of devices from rdesktop.c */
307     /* returns numer of units found and initialized. */
308 n-ki 612 /* optarg looks like ':h=/mnt/floppy,b=/mnt/usbdevice1' */
309 n-ki 569 /* when it arrives to this function. */
310     int
311 astrand 608 disk_enum_devices(uint32 * id, char *optarg)
312 n-ki 569 {
313     char *pos = optarg;
314     char *pos2;
315     int count = 0;
316    
317 stargo 865 /* skip the first colon */
318 n-ki 569 optarg++;
319     while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
320     {
321     pos2 = next_arg(optarg, '=');
322    
323 astrand 827 strncpy(g_rdpdr_device[*id].name, optarg, sizeof(g_rdpdr_device[*id].name) - 1);
324     if (strlen(optarg) > (sizeof(g_rdpdr_device[*id].name) - 1))
325 astrand 747 fprintf(stderr, "share name %s truncated to %s\n", optarg,
326     g_rdpdr_device[*id].name);
327 n-ki 569
328     g_rdpdr_device[*id].local_path = xmalloc(strlen(pos2) + 1);
329     strcpy(g_rdpdr_device[*id].local_path, pos2);
330     g_rdpdr_device[*id].device_type = DEVICE_TYPE_DISK;
331     count++;
332     (*id)++;
333    
334     optarg = pos;
335     }
336     return count;
337     }
338    
339 n-ki 596 /* Opens or creates a file or directory */
340 astrand 664 static NTSTATUS
341 n-ki 569 disk_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition,
342 jsorg71 776 uint32 flags_and_attributes, char *filename, NTHANDLE * phandle)
343 n-ki 569 {
344 jsorg71 776 NTHANDLE handle;
345 n-ki 569 DIR *dirp;
346     int flags, mode;
347 stargo 978 char path[PATH_MAX];
348 n-ki 600 struct stat filestat;
349 n-ki 569
350     handle = 0;
351     dirp = NULL;
352     flags = 0;
353     mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
354    
355 astrand 787 if (*filename && filename[strlen(filename) - 1] == '/')
356 n-ki 569 filename[strlen(filename) - 1] = 0;
357     sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename);
358    
359     switch (create_disposition)
360     {
361     case CREATE_ALWAYS:
362    
363 stargo 865 /* Delete existing file/link. */
364 n-ki 569 unlink(path);
365     flags |= O_CREAT;
366     break;
367    
368     case CREATE_NEW:
369    
370 stargo 865 /* If the file already exists, then fail. */
371 n-ki 569 flags |= O_CREAT | O_EXCL;
372     break;
373    
374     case OPEN_ALWAYS:
375    
376 stargo 865 /* Create if not already exists. */
377 n-ki 569 flags |= O_CREAT;
378     break;
379    
380     case OPEN_EXISTING:
381    
382 stargo 865 /* Default behaviour */
383 n-ki 569 break;
384    
385     case TRUNCATE_EXISTING:
386    
387 stargo 865 /* If the file does not exist, then fail. */
388 n-ki 569 flags |= O_TRUNC;
389     break;
390     }
391    
392 stargo 873 /*printf("Open: \"%s\" flags: %X, accessmask: %X sharemode: %X create disp: %X\n", path, flags_and_attributes, accessmask, sharemode, create_disposition); */
393 n-ki 597
394 stargo 865 /* Get information about file and set that flag ourselfs */
395 n-ki 597 if ((stat(path, &filestat) == 0) && (S_ISDIR(filestat.st_mode)))
396 n-ki 600 {
397     if (flags_and_attributes & FILE_NON_DIRECTORY_FILE)
398     return STATUS_FILE_IS_A_DIRECTORY;
399     else
400     flags_and_attributes |= FILE_DIRECTORY_FILE;
401     }
402 n-ki 597
403     if (flags_and_attributes & FILE_DIRECTORY_FILE)
404 n-ki 569 {
405 n-ki 597 if (flags & O_CREAT)
406 n-ki 569 {
407 n-ki 597 mkdir(path, mode);
408 n-ki 569 }
409    
410 n-ki 597 dirp = opendir(path);
411     if (!dirp)
412 n-ki 569 {
413     switch (errno)
414     {
415     case EACCES:
416    
417     return STATUS_ACCESS_DENIED;
418    
419     case ENOENT:
420    
421     return STATUS_NO_SUCH_FILE;
422    
423     default:
424    
425 n-ki 597 perror("opendir");
426 n-ki 569 return STATUS_NO_SUCH_FILE;
427     }
428     }
429 n-ki 597 handle = DIRFD(dirp);
430 n-ki 569 }
431 n-ki 597 else
432 n-ki 569 {
433 n-ki 596
434 n-ki 597 if (accessmask & GENERIC_ALL
435     || (accessmask & GENERIC_READ && accessmask & GENERIC_WRITE))
436 n-ki 569 {
437 n-ki 597 flags |= O_RDWR;
438 n-ki 569 }
439 n-ki 597 else if ((accessmask & GENERIC_WRITE) && !(accessmask & GENERIC_READ))
440 n-ki 569 {
441 n-ki 597 flags |= O_WRONLY;
442 n-ki 569 }
443 n-ki 597 else
444     {
445     flags |= O_RDONLY;
446     }
447 n-ki 569
448 astrand 790 handle = open_weak_exclusive(path, flags, mode);
449 n-ki 597 if (handle == -1)
450 n-ki 569 {
451     switch (errno)
452     {
453 n-ki 600 case EISDIR:
454    
455     return STATUS_FILE_IS_A_DIRECTORY;
456    
457 n-ki 569 case EACCES:
458    
459     return STATUS_ACCESS_DENIED;
460    
461     case ENOENT:
462    
463     return STATUS_NO_SUCH_FILE;
464 n-ki 612 case EEXIST:
465    
466     return STATUS_OBJECT_NAME_COLLISION;
467 n-ki 569 default:
468    
469 n-ki 597 perror("open");
470 n-ki 569 return STATUS_NO_SUCH_FILE;
471     }
472     }
473 n-ki 597
474     /* all read and writes of files should be non blocking */
475     if (fcntl(handle, F_SETFL, O_NONBLOCK) == -1)
476     perror("fcntl");
477 n-ki 569 }
478    
479     if (handle >= MAX_OPEN_FILES)
480     {
481     error("Maximum number of open files (%s) reached. Increase MAX_OPEN_FILES!\n",
482     handle);
483     exit(1);
484     }
485    
486     if (dirp)
487     g_fileinfo[handle].pdir = dirp;
488 stargo 795 else
489     g_fileinfo[handle].pdir = NULL;
490    
491 n-ki 569 g_fileinfo[handle].device_id = device_id;
492     g_fileinfo[handle].flags_and_attributes = flags_and_attributes;
493 stargo 795 g_fileinfo[handle].accessmask = accessmask;
494 astrand 986 strncpy(g_fileinfo[handle].path, path, PATH_MAX - 1);
495 stargo 795 g_fileinfo[handle].delete_on_close = False;
496     g_notify_stamp = True;
497 n-ki 569
498     *phandle = handle;
499     return STATUS_SUCCESS;
500     }
501    
502 astrand 664 static NTSTATUS
503 jsorg71 776 disk_close(NTHANDLE handle)
504 n-ki 569 {
505     struct fileinfo *pfinfo;
506    
507     pfinfo = &(g_fileinfo[handle]);
508    
509 stargo 795 g_notify_stamp = True;
510    
511     rdpdr_abort_io(handle, 0, STATUS_CANCELLED);
512    
513     if (pfinfo->pdir)
514 n-ki 569 {
515 stargo 795 if (closedir(pfinfo->pdir) < 0)
516     {
517     perror("closedir");
518     return STATUS_INVALID_HANDLE;
519     }
520    
521     if (pfinfo->delete_on_close)
522     if (rmdir(pfinfo->path) < 0)
523     {
524     perror(pfinfo->path);
525     return STATUS_ACCESS_DENIED;
526     }
527     pfinfo->delete_on_close = False;
528 n-ki 569 }
529     else
530     {
531 stargo 795 if (close(handle) < 0)
532     {
533     perror("close");
534     return STATUS_INVALID_HANDLE;
535     }
536     if (pfinfo->delete_on_close)
537     if (unlink(pfinfo->path) < 0)
538     {
539     perror(pfinfo->path);
540     return STATUS_ACCESS_DENIED;
541     }
542    
543     pfinfo->delete_on_close = False;
544 n-ki 569 }
545    
546     return STATUS_SUCCESS;
547     }
548    
549 astrand 664 static NTSTATUS
550 jsorg71 776 disk_read(NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
551 n-ki 569 {
552     int n;
553    
554 n-ki 600 #if 0
555 n-ki 596 /* browsing dir ???? */
556     /* each request is 24 bytes */
557     if (g_fileinfo[handle].flags_and_attributes & FILE_DIRECTORY_FILE)
558     {
559     *result = 0;
560     return STATUS_SUCCESS;
561     }
562 n-ki 600 #endif
563 n-ki 596
564 n-ki 613 lseek(handle, offset, SEEK_SET);
565    
566 n-ki 569 n = read(handle, data, length);
567    
568     if (n < 0)
569     {
570     *result = 0;
571 n-ki 600 switch (errno)
572     {
573     case EISDIR:
574 stargo 795 /* Implement 24 Byte directory read ??
575     with STATUS_NOT_IMPLEMENTED server doesn't read again */
576     /* return STATUS_FILE_IS_A_DIRECTORY; */
577     return STATUS_NOT_IMPLEMENTED;
578 n-ki 600 default:
579     perror("read");
580     return STATUS_INVALID_PARAMETER;
581     }
582 n-ki 569 }
583    
584     *result = n;
585    
586     return STATUS_SUCCESS;
587     }
588    
589 astrand 664 static NTSTATUS
590 jsorg71 776 disk_write(NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
591 n-ki 569 {
592     int n;
593    
594 n-ki 613 lseek(handle, offset, SEEK_SET);
595 n-ki 569
596     n = write(handle, data, length);
597    
598     if (n < 0)
599     {
600     perror("write");
601     *result = 0;
602 n-ki 600 switch (errno)
603     {
604     case ENOSPC:
605     return STATUS_DISK_FULL;
606     default:
607     return STATUS_ACCESS_DENIED;
608     }
609 n-ki 569 }
610    
611     *result = n;
612    
613     return STATUS_SUCCESS;
614     }
615    
616     NTSTATUS
617 jsorg71 776 disk_query_information(NTHANDLE handle, uint32 info_class, STREAM out)
618 n-ki 569 {
619     uint32 file_attributes, ft_high, ft_low;
620     struct stat filestat;
621     char *path, *filename;
622    
623     path = g_fileinfo[handle].path;
624    
625 stargo 865 /* Get information about file */
626 n-ki 569 if (fstat(handle, &filestat) != 0)
627     {
628     perror("stat");
629     out_uint8(out, 0);
630     return STATUS_ACCESS_DENIED;
631     }
632    
633 stargo 865 /* Set file attributes */
634 n-ki 569 file_attributes = 0;
635     if (S_ISDIR(filestat.st_mode))
636     file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
637 n-ki 600
638 n-ki 569 filename = 1 + strrchr(path, '/');
639     if (filename && filename[0] == '.')
640     file_attributes |= FILE_ATTRIBUTE_HIDDEN;
641    
642 n-ki 600 if (!file_attributes)
643     file_attributes |= FILE_ATTRIBUTE_NORMAL;
644    
645     if (!(filestat.st_mode & S_IWUSR))
646     file_attributes |= FILE_ATTRIBUTE_READONLY;
647    
648 stargo 865 /* Return requested data */
649 n-ki 569 switch (info_class)
650     {
651 astrand 653 case FileBasicInformation:
652 n-ki 600 seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high,
653     &ft_low);
654 stargo 865 out_uint32_le(out, ft_low); /* create_access_time */
655 n-ki 600 out_uint32_le(out, ft_high);
656 n-ki 569
657     seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low);
658 stargo 865 out_uint32_le(out, ft_low); /* last_access_time */
659 n-ki 569 out_uint32_le(out, ft_high);
660    
661     seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low);
662 stargo 865 out_uint32_le(out, ft_low); /* last_write_time */
663 n-ki 569 out_uint32_le(out, ft_high);
664    
665 n-ki 600 seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low);
666 stargo 865 out_uint32_le(out, ft_low); /* last_change_time */
667 n-ki 600 out_uint32_le(out, ft_high);
668    
669 n-ki 569 out_uint32_le(out, file_attributes);
670     break;
671    
672 astrand 653 case FileStandardInformation:
673 n-ki 569
674 stargo 865 out_uint32_le(out, filestat.st_size); /* Allocation size */
675 n-ki 569 out_uint32_le(out, 0);
676 stargo 865 out_uint32_le(out, filestat.st_size); /* End of file */
677 n-ki 569 out_uint32_le(out, 0);
678 stargo 865 out_uint32_le(out, filestat.st_nlink); /* Number of links */
679     out_uint8(out, 0); /* Delete pending */
680     out_uint8(out, S_ISDIR(filestat.st_mode) ? 1 : 0); /* Directory */
681 n-ki 569 break;
682    
683 astrand 653 case FileObjectIdInformation:
684 n-ki 569
685     out_uint32_le(out, file_attributes); /* File Attributes */
686     out_uint32_le(out, 0); /* Reparse Tag */
687     break;
688    
689     default:
690    
691     unimpl("IRP Query (File) Information class: 0x%x\n", info_class);
692     return STATUS_INVALID_PARAMETER;
693     }
694     return STATUS_SUCCESS;
695     }
696    
697     NTSTATUS
698 jsorg71 776 disk_set_information(NTHANDLE handle, uint32 info_class, STREAM in, STREAM out)
699 n-ki 569 {
700 stargo 795 uint32 length, file_attributes, ft_high, ft_low, delete_on_close;
701 stargo 978 char newname[PATH_MAX], fullpath[PATH_MAX];
702 n-ki 569 struct fileinfo *pfinfo;
703 n-ki 600 int mode;
704     struct stat filestat;
705     time_t write_time, change_time, access_time, mod_time;
706     struct utimbuf tvs;
707 n-ki 612 struct STATFS_T stat_fs;
708 n-ki 600
709 n-ki 569 pfinfo = &(g_fileinfo[handle]);
710 stargo 795 g_notify_stamp = True;
711 n-ki 569
712     switch (info_class)
713     {
714 astrand 653 case FileBasicInformation:
715 n-ki 600 write_time = change_time = access_time = 0;
716 n-ki 569
717 n-ki 600 in_uint8s(in, 4); /* Handle of root dir? */
718     in_uint8s(in, 24); /* unknown */
719    
720 stargo 865 /* CreationTime */
721 n-ki 600 in_uint32_le(in, ft_low);
722     in_uint32_le(in, ft_high);
723    
724 stargo 865 /* AccessTime */
725 n-ki 600 in_uint32_le(in, ft_low);
726     in_uint32_le(in, ft_high);
727     if (ft_low || ft_high)
728     access_time = convert_1970_to_filetime(ft_high, ft_low);
729    
730 stargo 865 /* WriteTime */
731 n-ki 600 in_uint32_le(in, ft_low);
732     in_uint32_le(in, ft_high);
733     if (ft_low || ft_high)
734     write_time = convert_1970_to_filetime(ft_high, ft_low);
735    
736 stargo 865 /* ChangeTime */
737 n-ki 600 in_uint32_le(in, ft_low);
738     in_uint32_le(in, ft_high);
739     if (ft_low || ft_high)
740     change_time = convert_1970_to_filetime(ft_high, ft_low);
741    
742     in_uint32_le(in, file_attributes);
743    
744     if (fstat(handle, &filestat))
745     return STATUS_ACCESS_DENIED;
746    
747     tvs.modtime = filestat.st_mtime;
748     tvs.actime = filestat.st_atime;
749     if (access_time)
750     tvs.actime = access_time;
751    
752    
753     if (write_time || change_time)
754     mod_time = MIN(write_time, change_time);
755     else
756     mod_time = write_time ? write_time : change_time;
757    
758     if (mod_time)
759     tvs.modtime = mod_time;
760    
761    
762     if (access_time || write_time || change_time)
763     {
764     #if WITH_DEBUG_RDP5
765     printf("FileBasicInformation access time %s",
766     ctime(&tvs.actime));
767     printf("FileBasicInformation modification time %s",
768     ctime(&tvs.modtime));
769     #endif
770 stargo 795 if (utime(pfinfo->path, &tvs) && errno != EPERM)
771 n-ki 600 return STATUS_ACCESS_DENIED;
772     }
773    
774     if (!file_attributes)
775 stargo 865 break; /* not valid */
776 n-ki 600
777     mode = filestat.st_mode;
778    
779     if (file_attributes & FILE_ATTRIBUTE_READONLY)
780     mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
781     else
782     mode |= S_IWUSR;
783    
784     mode &= 0777;
785     #if WITH_DEBUG_RDP5
786     printf("FileBasicInformation set access mode 0%o", mode);
787     #endif
788    
789     if (fchmod(handle, mode))
790     return STATUS_ACCESS_DENIED;
791 n-ki 612
792 n-ki 569 break;
793    
794 astrand 653 case FileRenameInformation:
795 n-ki 569
796     in_uint8s(in, 4); /* Handle of root dir? */
797     in_uint8s(in, 0x1a); /* unknown */
798     in_uint32_le(in, length);
799    
800     if (length && (length / 2) < 256)
801     {
802     rdp_in_unistr(in, newname, length);
803     convert_to_unix_filename(newname);
804     }
805     else
806     {
807     return STATUS_INVALID_PARAMETER;
808     }
809    
810     sprintf(fullpath, "%s%s", g_rdpdr_device[pfinfo->device_id].local_path,
811     newname);
812    
813     if (rename(pfinfo->path, fullpath) != 0)
814     {
815     perror("rename");
816     return STATUS_ACCESS_DENIED;
817     }
818     break;
819    
820 astrand 653 case FileDispositionInformation:
821 astrand 659 /* As far as I understand it, the correct
822     thing to do here is to *schedule* a delete,
823     so it will be deleted when the file is
824     closed. Subsequent
825     FileDispositionInformation requests with
826     DeleteFile set to FALSE should unschedule
827     the delete. See
828 stargo 795 http://www.osronline.com/article.cfm?article=245. */
829 n-ki 569
830 stargo 795 in_uint32_le(in, delete_on_close);
831 n-ki 601
832 stargo 795 if (delete_on_close ||
833     (pfinfo->
834     accessmask & (FILE_DELETE_ON_CLOSE | FILE_COMPLETE_IF_OPLOCKED)))
835 n-ki 601 {
836 stargo 795 pfinfo->delete_on_close = True;
837 n-ki 601 }
838    
839 n-ki 569 break;
840    
841 astrand 653 case FileAllocationInformation:
842 astrand 661 /* Fall through to FileEndOfFileInformation,
843     which uses ftrunc. This is like Samba with
844     "strict allocation = false", and means that
845     we won't detect out-of-quota errors, for
846     example. */
847 n-ki 569
848 astrand 653 case FileEndOfFileInformation:
849 n-ki 600 in_uint8s(in, 28); /* unknown */
850     in_uint32_le(in, length); /* file size */
851 n-ki 569
852 n-ki 616 /* prevents start of writing if not enough space left on device */
853     if (STATFS_FN(g_rdpdr_device[pfinfo->device_id].local_path, &stat_fs) == 0)
854 stargo 795 if (stat_fs.f_bfree * stat_fs.f_bsize < length)
855 n-ki 616 return STATUS_DISK_FULL;
856    
857 astrand 785 if (ftruncate_growable(handle, length) != 0)
858 astrand 661 {
859     return STATUS_DISK_FULL;
860     }
861    
862 n-ki 569 break;
863     default:
864    
865     unimpl("IRP Set File Information class: 0x%x\n", info_class);
866     return STATUS_INVALID_PARAMETER;
867     }
868     return STATUS_SUCCESS;
869     }
870    
871 stargo 795 NTSTATUS
872     disk_check_notify(NTHANDLE handle)
873     {
874     struct fileinfo *pfinfo;
875     NTSTATUS status = STATUS_PENDING;
876    
877     NOTIFY notify;
878    
879     pfinfo = &(g_fileinfo[handle]);
880     if (!pfinfo->pdir)
881     return STATUS_INVALID_DEVICE_REQUEST;
882    
883    
884    
885     status = NotifyInfo(handle, pfinfo->info_class, &notify);
886    
887     if (status != STATUS_PENDING)
888     return status;
889    
890     if (memcmp(&pfinfo->notify, &notify, sizeof(NOTIFY)))
891     {
892 stargo 873 /*printf("disk_check_notify found changed event\n"); */
893 stargo 795 memcpy(&pfinfo->notify, &notify, sizeof(NOTIFY));
894     status = STATUS_NOTIFY_ENUM_DIR;
895     }
896    
897     return status;
898    
899    
900     }
901    
902     NTSTATUS
903     disk_create_notify(NTHANDLE handle, uint32 info_class)
904     {
905    
906     struct fileinfo *pfinfo;
907     NTSTATUS ret = STATUS_PENDING;
908    
909     /* printf("start disk_create_notify info_class %X\n", info_class); */
910    
911     pfinfo = &(g_fileinfo[handle]);
912     pfinfo->info_class = info_class;
913    
914     ret = NotifyInfo(handle, info_class, &pfinfo->notify);
915    
916     if (info_class & 0x1000)
917     { /* ???? */
918     if (ret == STATUS_PENDING)
919     return STATUS_SUCCESS;
920     }
921    
922     /* printf("disk_create_notify: num_entries %d\n", pfinfo->notify.num_entries); */
923    
924    
925     return ret;
926    
927     }
928    
929     static NTSTATUS
930     NotifyInfo(NTHANDLE handle, uint32 info_class, NOTIFY * p)
931     {
932     struct fileinfo *pfinfo;
933     struct stat buf;
934     struct dirent *dp;
935     char *fullname;
936     DIR *dpr;
937    
938     pfinfo = &(g_fileinfo[handle]);
939     if (fstat(handle, &buf) < 0)
940     {
941     perror("NotifyInfo");
942     return STATUS_ACCESS_DENIED;
943     }
944     p->modify_time = buf.st_mtime;
945     p->status_time = buf.st_ctime;
946     p->num_entries = 0;
947     p->total_time = 0;
948    
949    
950     dpr = opendir(pfinfo->path);
951     if (!dpr)
952     {
953     perror("NotifyInfo");
954     return STATUS_ACCESS_DENIED;
955     }
956    
957    
958     while ((dp = readdir(dpr)))
959     {
960     if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
961     continue;
962     p->num_entries++;
963     fullname = xmalloc(strlen(pfinfo->path) + strlen(dp->d_name) + 2);
964     sprintf(fullname, "%s/%s", pfinfo->path, dp->d_name);
965    
966     if (!stat(fullname, &buf))
967     {
968     p->total_time += (buf.st_mtime + buf.st_ctime);
969     }
970    
971     xfree(fullname);
972     }
973     closedir(dpr);
974    
975     return STATUS_PENDING;
976     }
977    
978 astrand 664 static FsInfoType *
979 n-ki 615 FsVolumeInfo(char *fpath)
980     {
981    
982 stargo 795 static FsInfoType info;
983 stargo 873 #ifdef USE_SETMNTENT
984 stargo 832 FILE *fdfs;
985 n-ki 615 struct mntent *e;
986 stargo 795 #endif
987 n-ki 615
988     /* initialize */
989     memset(&info, 0, sizeof(info));
990     strcpy(info.label, "RDESKTOP");
991     strcpy(info.type, "RDPFS");
992    
993 stargo 873 #ifdef USE_SETMNTENT
994 n-ki 615 fdfs = setmntent(MNTENT_PATH, "r");
995     if (!fdfs)
996     return &info;
997    
998     while ((e = getmntent(fdfs)))
999     {
1000 astrand 1010 if (str_startswith(e->mnt_dir, fpath))
1001 n-ki 615 {
1002     strcpy(info.type, e->mnt_type);
1003     strcpy(info.name, e->mnt_fsname);
1004     if (strstr(e->mnt_opts, "vfat") || strstr(e->mnt_opts, "iso9660"))
1005     {
1006     int fd = open(e->mnt_fsname, O_RDONLY);
1007     if (fd >= 0)
1008     {
1009     unsigned char buf[512];
1010     memset(buf, 0, sizeof(buf));
1011     if (strstr(e->mnt_opts, "vfat"))
1012     /*FAT*/
1013     {
1014     strcpy(info.type, "vfat");
1015     read(fd, buf, sizeof(buf));
1016     info.serial =
1017     (buf[42] << 24) + (buf[41] << 16) +
1018     (buf[40] << 8) + buf[39];
1019     strncpy(info.label, buf + 43, 10);
1020     info.label[10] = '\0';
1021     }
1022     else if (lseek(fd, 32767, SEEK_SET) >= 0) /* ISO9660 */
1023     {
1024     read(fd, buf, sizeof(buf));
1025     strncpy(info.label, buf + 41, 32);
1026     info.label[32] = '\0';
1027 stargo 865 /* info.Serial = (buf[128]<<24)+(buf[127]<<16)+(buf[126]<<8)+buf[125]; */
1028 n-ki 615 }
1029     close(fd);
1030     }
1031     }
1032     }
1033     }
1034     endmntent(fdfs);
1035     #else
1036     /* initialize */
1037     memset(&info, 0, sizeof(info));
1038     strcpy(info.label, "RDESKTOP");
1039     strcpy(info.type, "RDPFS");
1040    
1041     #endif
1042     return &info;
1043     }
1044    
1045    
1046 n-ki 569 NTSTATUS
1047 jsorg71 776 disk_query_volume_information(NTHANDLE handle, uint32 info_class, STREAM out)
1048 n-ki 569 {
1049 stargo 574 struct STATFS_T stat_fs;
1050 n-ki 569 struct fileinfo *pfinfo;
1051 n-ki 615 FsInfoType *fsinfo;
1052 n-ki 569
1053     pfinfo = &(g_fileinfo[handle]);
1054    
1055 n-ki 600 if (STATFS_FN(pfinfo->path, &stat_fs) != 0)
1056 n-ki 569 {
1057     perror("statfs");
1058     return STATUS_ACCESS_DENIED;
1059     }
1060    
1061 n-ki 615 fsinfo = FsVolumeInfo(pfinfo->path);
1062    
1063 n-ki 569 switch (info_class)
1064     {
1065 astrand 653 case FileFsVolumeInformation:
1066 n-ki 569
1067     out_uint32_le(out, 0); /* volume creation time low */
1068     out_uint32_le(out, 0); /* volume creation time high */
1069 n-ki 615 out_uint32_le(out, fsinfo->serial); /* serial */
1070    
1071     out_uint32_le(out, 2 * strlen(fsinfo->label)); /* length of string */
1072    
1073 n-ki 569 out_uint8(out, 0); /* support objects? */
1074 n-ki 615 rdp_out_unistr(out, fsinfo->label, 2 * strlen(fsinfo->label) - 2);
1075 n-ki 569 break;
1076    
1077 astrand 653 case FileFsSizeInformation:
1078 n-ki 569
1079     out_uint32_le(out, stat_fs.f_blocks); /* Total allocation units low */
1080     out_uint32_le(out, 0); /* Total allocation high units */
1081     out_uint32_le(out, stat_fs.f_bfree); /* Available allocation units */
1082     out_uint32_le(out, 0); /* Available allowcation units */
1083     out_uint32_le(out, stat_fs.f_bsize / 0x200); /* Sectors per allocation unit */
1084     out_uint32_le(out, 0x200); /* Bytes per sector */
1085     break;
1086    
1087 astrand 653 case FileFsAttributeInformation:
1088 n-ki 569
1089     out_uint32_le(out, FS_CASE_SENSITIVE | FS_CASE_IS_PRESERVED); /* fs attributes */
1090 stargo 574 out_uint32_le(out, F_NAMELEN(stat_fs)); /* max length of filename */
1091 n-ki 615
1092     out_uint32_le(out, 2 * strlen(fsinfo->type)); /* length of fs_type */
1093     rdp_out_unistr(out, fsinfo->type, 2 * strlen(fsinfo->type) - 2);
1094 n-ki 569 break;
1095    
1096 astrand 653 case FileFsLabelInformation:
1097     case FileFsDeviceInformation:
1098     case FileFsControlInformation:
1099     case FileFsFullSizeInformation:
1100     case FileFsObjectIdInformation:
1101     case FileFsMaximumInformation:
1102    
1103 n-ki 569 default:
1104    
1105     unimpl("IRP Query Volume Information class: 0x%x\n", info_class);
1106     return STATUS_INVALID_PARAMETER;
1107     }
1108     return STATUS_SUCCESS;
1109     }
1110    
1111     NTSTATUS
1112 jsorg71 776 disk_query_directory(NTHANDLE handle, uint32 info_class, char *pattern, STREAM out)
1113 n-ki 569 {
1114     uint32 file_attributes, ft_low, ft_high;
1115 stargo 978 char *dirname, fullpath[PATH_MAX];
1116 n-ki 569 DIR *pdir;
1117     struct dirent *pdirent;
1118     struct stat fstat;
1119     struct fileinfo *pfinfo;
1120    
1121     pfinfo = &(g_fileinfo[handle]);
1122     pdir = pfinfo->pdir;
1123     dirname = pfinfo->path;
1124     file_attributes = 0;
1125    
1126     switch (info_class)
1127     {
1128 astrand 696 case FileBothDirectoryInformation:
1129 n-ki 569
1130 stargo 865 /* If a search pattern is received, remember this pattern, and restart search */
1131 n-ki 569 if (pattern[0] != 0)
1132     {
1133 astrand 986 strncpy(pfinfo->pattern, 1 + strrchr(pattern, '/'), PATH_MAX - 1);
1134 n-ki 569 rewinddir(pdir);
1135     }
1136    
1137 stargo 865 /* find next dirent matching pattern */
1138 n-ki 569 pdirent = readdir(pdir);
1139     while (pdirent && fnmatch(pfinfo->pattern, pdirent->d_name, 0) != 0)
1140     pdirent = readdir(pdir);
1141    
1142     if (pdirent == NULL)
1143     return STATUS_NO_MORE_FILES;
1144    
1145 stargo 865 /* Get information for directory entry */
1146 n-ki 569 sprintf(fullpath, "%s/%s", dirname, pdirent->d_name);
1147 n-ki 600
1148 n-ki 569 if (stat(fullpath, &fstat))
1149     {
1150 astrand 698 switch (errno)
1151     {
1152     case ENOENT:
1153     case ELOOP:
1154     case EACCES:
1155     /* These are non-fatal errors. */
1156     memset(&fstat, 0, sizeof(fstat));
1157     break;
1158     default:
1159     /* Fatal error. By returning STATUS_NO_SUCH_FILE,
1160     the directory list operation will be aborted */
1161     perror(fullpath);
1162     out_uint8(out, 0);
1163     return STATUS_NO_SUCH_FILE;
1164     }
1165 n-ki 569 }
1166    
1167     if (S_ISDIR(fstat.st_mode))
1168     file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
1169     if (pdirent->d_name[0] == '.')
1170     file_attributes |= FILE_ATTRIBUTE_HIDDEN;
1171 n-ki 600 if (!file_attributes)
1172     file_attributes |= FILE_ATTRIBUTE_NORMAL;
1173     if (!(fstat.st_mode & S_IWUSR))
1174     file_attributes |= FILE_ATTRIBUTE_READONLY;
1175 n-ki 569
1176 stargo 865 /* Return requested information */
1177     out_uint8s(out, 8); /* unknown zero */
1178 n-ki 569
1179 n-ki 600 seconds_since_1970_to_filetime(get_create_time(&fstat), &ft_high, &ft_low);
1180 stargo 865 out_uint32_le(out, ft_low); /* create time */
1181 n-ki 600 out_uint32_le(out, ft_high);
1182    
1183 n-ki 569 seconds_since_1970_to_filetime(fstat.st_atime, &ft_high, &ft_low);
1184 stargo 865 out_uint32_le(out, ft_low); /* last_access_time */
1185 n-ki 569 out_uint32_le(out, ft_high);
1186    
1187     seconds_since_1970_to_filetime(fstat.st_mtime, &ft_high, &ft_low);
1188 stargo 865 out_uint32_le(out, ft_low); /* last_write_time */
1189 n-ki 569 out_uint32_le(out, ft_high);
1190    
1191 n-ki 600 seconds_since_1970_to_filetime(fstat.st_ctime, &ft_high, &ft_low);
1192 stargo 865 out_uint32_le(out, ft_low); /* change_write_time */
1193 n-ki 600 out_uint32_le(out, ft_high);
1194    
1195 stargo 865 out_uint32_le(out, fstat.st_size); /* filesize low */
1196     out_uint32_le(out, 0); /* filesize high */
1197     out_uint32_le(out, fstat.st_size); /* filesize low */
1198     out_uint32_le(out, 0); /* filesize high */
1199 n-ki 569 out_uint32_le(out, file_attributes);
1200 stargo 865 out_uint8(out, 2 * strlen(pdirent->d_name) + 2); /* unicode length */
1201     out_uint8s(out, 7); /* pad? */
1202     out_uint8(out, 0); /* 8.3 file length */
1203     out_uint8s(out, 2 * 12); /* 8.3 unicode length */
1204 n-ki 569 rdp_out_unistr(out, pdirent->d_name, 2 * strlen(pdirent->d_name));
1205     break;
1206    
1207     default:
1208 astrand 696 /* FIXME: Support FileDirectoryInformation,
1209     FileFullDirectoryInformation, and
1210     FileNamesInformation */
1211 n-ki 569
1212     unimpl("IRP Query Directory sub: 0x%x\n", info_class);
1213     return STATUS_INVALID_PARAMETER;
1214     }
1215    
1216     return STATUS_SUCCESS;
1217     }
1218    
1219 n-ki 600
1220    
1221     static NTSTATUS
1222 jsorg71 776 disk_device_control(NTHANDLE handle, uint32 request, STREAM in, STREAM out)
1223 n-ki 600 {
1224     if (((request >> 16) != 20) || ((request >> 16) != 9))
1225     return STATUS_INVALID_PARAMETER;
1226    
1227     /* extract operation */
1228     request >>= 2;
1229     request &= 0xfff;
1230    
1231     printf("DISK IOCTL %d\n", request);
1232    
1233     switch (request)
1234     {
1235 stargo 865 case 25: /* ? */
1236     case 42: /* ? */
1237 n-ki 600 default:
1238     unimpl("DISK IOCTL %d\n", request);
1239     return STATUS_INVALID_PARAMETER;
1240     }
1241    
1242     return STATUS_SUCCESS;
1243     }
1244    
1245 n-ki 569 DEVICE_FNS disk_fns = {
1246     disk_create,
1247     disk_close,
1248     disk_read,
1249     disk_write,
1250 n-ki 600 disk_device_control /* device_control */
1251 n-ki 569 };

  ViewVC Help
Powered by ViewVC 1.1.26