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

Annotation of /sourceforge.net/trunk/rdesktop/disk.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 873 - (hide annotations)
Sat Apr 2 17:31:27 2005 UTC (19 years, 1 month ago) by stargo
File MIME type: text/plain
File size: 28170 byte(s)
Use configure to determine stat(v)fs and setmntent
Tested on:
 * Debian GNU/Linux 3.1
 * Solaris 9/10
 * Mac OSX 10.3
 * HP/UX 10.20
 * OpenBSD 3.4

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 572
31 n-ki 600 #include <utime.h>
32     #include <time.h> /* ctime */
33    
34 stargo 759 #if (defined(HAVE_DIRFD) || (HAVE_DECL_DIRFD == 1))
35 stargo 742 #define DIRFD(a) (dirfd(a))
36     #else
37     #define DIRFD(a) ((a)->DIR_FD_MEMBER_NAME)
38     #endif
39 n-ki 600
40 stargo 873 /* TODO: Fix mntent-handling for solaris
41     * #include <sys/mntent.h> */
42     #if (defined(HAVE_MNTENT_H) && defined(HAVE_SETMNTENT))
43     #include <mntent.h>
44     #define MNTENT_PATH "/etc/mtab"
45     #define USE_SETMNTENT
46 stargo 742 #endif
47    
48 stargo 873 #ifdef HAVE_SYS_VFS_H
49     #include <sys/vfs.h>
50     #endif
51 stargo 573
52 stargo 873 #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     #ifdef HAVE_SYS_PARAM_H
61 stargo 573 #include <sys/param.h>
62 stargo 873 #endif
63    
64     #ifdef HAVE_SYS_MOUNT_H
65 stargo 573 #include <sys/mount.h>
66 stargo 873 #endif
67    
68     #include "rdesktop.h"
69    
70     #ifdef STAT_STATFS3_OSF1
71     #define STATFS_FN(path, buf) (statfs(path,buf,sizeof(buf)))
72 stargo 574 #define STATFS_T statfs
73 stargo 873 #define USE_STATFS
74     #endif
75 stargo 573
76 stargo 873 #ifdef STAT_STATVFS
77 stargo 745 #define STATFS_FN(path, buf) (statvfs(path,buf))
78     #define STATFS_T statvfs
79 stargo 873 #define USE_STATVFS
80     #endif
81 stargo 745
82 stargo 873 #ifdef STAT_STATVFS64
83     #define STATFS_FN(path, buf) (statvfs64(path,buf))
84     #define STATFS_T statvfs64
85     #define USE_STATVFS
86     #endif
87 stargo 807
88 stargo 873 #if (defined(STAT_STATFS2_FS_DATA) || defined(STAT_STATFS2_BSIZE) || defined(STAT_STATFS2_FSIZE))
89 stargo 574 #define STATFS_FN(path, buf) (statfs(path,buf))
90     #define STATFS_T statfs
91 stargo 873 #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 stargo 573 #define F_NAMELEN(buf) ((buf).f_namelen)
106 stargo 572 #endif
107    
108 stargo 873 #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 n-ki 569 extern RDPDR_DEVICE g_rdpdr_device[];
125    
126 n-ki 627 FILEINFO g_fileinfo[MAX_OPEN_FILES];
127 stargo 795 BOOL g_notify_stamp = False;
128 n-ki 569
129 n-ki 615 typedef struct
130     {
131     char name[256];
132     char label[256];
133     unsigned long serial;
134     char type[256];
135     } FsInfoType;
136    
137 stargo 795 static NTSTATUS NotifyInfo(NTHANDLE handle, uint32 info_class, NOTIFY * p);
138 n-ki 615
139 astrand 664 static time_t
140 n-ki 600 get_create_time(struct stat *st)
141     {
142     time_t ret, ret1;
143    
144     ret = MIN(st->st_ctime, st->st_mtime);
145     ret1 = MIN(ret, st->st_atime);
146    
147     if (ret1 != (time_t) 0)
148     return ret1;
149    
150     return ret;
151     }
152    
153 n-ki 569 /* Convert seconds since 1970 to a filetime */
154 astrand 664 static void
155 n-ki 569 seconds_since_1970_to_filetime(time_t seconds, uint32 * high, uint32 * low)
156     {
157     unsigned long long ticks;
158    
159     ticks = (seconds + 11644473600LL) * 10000000;
160     *low = (uint32) ticks;
161     *high = (uint32) (ticks >> 32);
162     }
163    
164 n-ki 600 /* Convert seconds since 1970 back to filetime */
165 astrand 664 static time_t
166 n-ki 600 convert_1970_to_filetime(uint32 high, uint32 low)
167     {
168     unsigned long long ticks;
169     time_t val;
170    
171     ticks = low + (((unsigned long long) high) << 32);
172     ticks /= 10000000;
173     ticks -= 11644473600LL;
174    
175     val = (time_t) ticks;
176     return (val);
177    
178     }
179    
180 astrand 785 /* 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 n-ki 600
190 astrand 785 /* 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 astrand 790 /* 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 astrand 785
251 astrand 790 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 n-ki 569 /* Enumeration of devices from rdesktop.c */
291     /* returns numer of units found and initialized. */
292 n-ki 612 /* optarg looks like ':h=/mnt/floppy,b=/mnt/usbdevice1' */
293 n-ki 569 /* when it arrives to this function. */
294     int
295 astrand 608 disk_enum_devices(uint32 * id, char *optarg)
296 n-ki 569 {
297     char *pos = optarg;
298     char *pos2;
299     int count = 0;
300    
301 stargo 865 /* skip the first colon */
302 n-ki 569 optarg++;
303     while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
304     {
305     pos2 = next_arg(optarg, '=');
306    
307 astrand 827 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 astrand 747 fprintf(stderr, "share name %s truncated to %s\n", optarg,
310     g_rdpdr_device[*id].name);
311 n-ki 569
312     g_rdpdr_device[*id].local_path = xmalloc(strlen(pos2) + 1);
313     strcpy(g_rdpdr_device[*id].local_path, pos2);
314     g_rdpdr_device[*id].device_type = DEVICE_TYPE_DISK;
315     count++;
316     (*id)++;
317    
318     optarg = pos;
319     }
320     return count;
321     }
322    
323 n-ki 596 /* Opens or creates a file or directory */
324 astrand 664 static NTSTATUS
325 n-ki 569 disk_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition,
326 jsorg71 776 uint32 flags_and_attributes, char *filename, NTHANDLE * phandle)
327 n-ki 569 {
328 jsorg71 776 NTHANDLE handle;
329 n-ki 569 DIR *dirp;
330     int flags, mode;
331     char path[256];
332 n-ki 600 struct stat filestat;
333 n-ki 569
334     handle = 0;
335     dirp = NULL;
336     flags = 0;
337     mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
338    
339 astrand 787 if (*filename && filename[strlen(filename) - 1] == '/')
340 n-ki 569 filename[strlen(filename) - 1] = 0;
341     sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename);
342    
343     switch (create_disposition)
344     {
345     case CREATE_ALWAYS:
346    
347 stargo 865 /* Delete existing file/link. */
348 n-ki 569 unlink(path);
349     flags |= O_CREAT;
350     break;
351    
352     case CREATE_NEW:
353    
354 stargo 865 /* If the file already exists, then fail. */
355 n-ki 569 flags |= O_CREAT | O_EXCL;
356     break;
357    
358     case OPEN_ALWAYS:
359    
360 stargo 865 /* Create if not already exists. */
361 n-ki 569 flags |= O_CREAT;
362     break;
363    
364     case OPEN_EXISTING:
365    
366 stargo 865 /* Default behaviour */
367 n-ki 569 break;
368    
369     case TRUNCATE_EXISTING:
370    
371 stargo 865 /* If the file does not exist, then fail. */
372 n-ki 569 flags |= O_TRUNC;
373     break;
374     }
375    
376 stargo 873 /*printf("Open: \"%s\" flags: %X, accessmask: %X sharemode: %X create disp: %X\n", path, flags_and_attributes, accessmask, sharemode, create_disposition); */
377 n-ki 597
378 stargo 865 /* Get information about file and set that flag ourselfs */
379 n-ki 597 if ((stat(path, &filestat) == 0) && (S_ISDIR(filestat.st_mode)))
380 n-ki 600 {
381     if (flags_and_attributes & FILE_NON_DIRECTORY_FILE)
382     return STATUS_FILE_IS_A_DIRECTORY;
383     else
384     flags_and_attributes |= FILE_DIRECTORY_FILE;
385     }
386 n-ki 597
387     if (flags_and_attributes & FILE_DIRECTORY_FILE)
388 n-ki 569 {
389 n-ki 597 if (flags & O_CREAT)
390 n-ki 569 {
391 n-ki 597 mkdir(path, mode);
392 n-ki 569 }
393    
394 n-ki 597 dirp = opendir(path);
395     if (!dirp)
396 n-ki 569 {
397     switch (errno)
398     {
399     case EACCES:
400    
401     return STATUS_ACCESS_DENIED;
402    
403     case ENOENT:
404    
405     return STATUS_NO_SUCH_FILE;
406    
407     default:
408    
409 n-ki 597 perror("opendir");
410 n-ki 569 return STATUS_NO_SUCH_FILE;
411     }
412     }
413 n-ki 597 handle = DIRFD(dirp);
414 n-ki 569 }
415 n-ki 597 else
416 n-ki 569 {
417 n-ki 596
418 n-ki 597 if (accessmask & GENERIC_ALL
419     || (accessmask & GENERIC_READ && accessmask & GENERIC_WRITE))
420 n-ki 569 {
421 n-ki 597 flags |= O_RDWR;
422 n-ki 569 }
423 n-ki 597 else if ((accessmask & GENERIC_WRITE) && !(accessmask & GENERIC_READ))
424 n-ki 569 {
425 n-ki 597 flags |= O_WRONLY;
426 n-ki 569 }
427 n-ki 597 else
428     {
429     flags |= O_RDONLY;
430     }
431 n-ki 569
432 astrand 790 handle = open_weak_exclusive(path, flags, mode);
433 n-ki 597 if (handle == -1)
434 n-ki 569 {
435     switch (errno)
436     {
437 n-ki 600 case EISDIR:
438    
439     return STATUS_FILE_IS_A_DIRECTORY;
440    
441 n-ki 569 case EACCES:
442    
443     return STATUS_ACCESS_DENIED;
444    
445     case ENOENT:
446    
447     return STATUS_NO_SUCH_FILE;
448 n-ki 612 case EEXIST:
449    
450     return STATUS_OBJECT_NAME_COLLISION;
451 n-ki 569 default:
452    
453 n-ki 597 perror("open");
454 n-ki 569 return STATUS_NO_SUCH_FILE;
455     }
456     }
457 n-ki 597
458     /* all read and writes of files should be non blocking */
459     if (fcntl(handle, F_SETFL, O_NONBLOCK) == -1)
460     perror("fcntl");
461 n-ki 569 }
462    
463     if (handle >= MAX_OPEN_FILES)
464     {
465     error("Maximum number of open files (%s) reached. Increase MAX_OPEN_FILES!\n",
466     handle);
467     exit(1);
468     }
469    
470     if (dirp)
471     g_fileinfo[handle].pdir = dirp;
472 stargo 795 else
473     g_fileinfo[handle].pdir = NULL;
474    
475 n-ki 569 g_fileinfo[handle].device_id = device_id;
476     g_fileinfo[handle].flags_and_attributes = flags_and_attributes;
477 stargo 795 g_fileinfo[handle].accessmask = accessmask;
478 n-ki 569 strncpy(g_fileinfo[handle].path, path, 255);
479 stargo 795 g_fileinfo[handle].delete_on_close = False;
480     g_notify_stamp = True;
481 n-ki 569
482     *phandle = handle;
483     return STATUS_SUCCESS;
484     }
485    
486 astrand 664 static NTSTATUS
487 jsorg71 776 disk_close(NTHANDLE handle)
488 n-ki 569 {
489     struct fileinfo *pfinfo;
490    
491     pfinfo = &(g_fileinfo[handle]);
492    
493 stargo 795 g_notify_stamp = True;
494    
495     rdpdr_abort_io(handle, 0, STATUS_CANCELLED);
496    
497     if (pfinfo->pdir)
498 n-ki 569 {
499 stargo 795 if (closedir(pfinfo->pdir) < 0)
500     {
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 n-ki 569 }
513     else
514     {
515 stargo 795 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 n-ki 569 }
529    
530     return STATUS_SUCCESS;
531     }
532    
533 astrand 664 static NTSTATUS
534 jsorg71 776 disk_read(NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
535 n-ki 569 {
536     int n;
537    
538 n-ki 600 #if 0
539 n-ki 596 /* browsing dir ???? */
540     /* each request is 24 bytes */
541     if (g_fileinfo[handle].flags_and_attributes & FILE_DIRECTORY_FILE)
542     {
543     *result = 0;
544     return STATUS_SUCCESS;
545     }
546 n-ki 600 #endif
547 n-ki 596
548 n-ki 613 lseek(handle, offset, SEEK_SET);
549    
550 n-ki 569 n = read(handle, data, length);
551    
552     if (n < 0)
553     {
554     *result = 0;
555 n-ki 600 switch (errno)
556     {
557     case EISDIR:
558 stargo 795 /* 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 n-ki 600 default:
563     perror("read");
564     return STATUS_INVALID_PARAMETER;
565     }
566 n-ki 569 }
567    
568     *result = n;
569    
570     return STATUS_SUCCESS;
571     }
572    
573 astrand 664 static NTSTATUS
574 jsorg71 776 disk_write(NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
575 n-ki 569 {
576     int n;
577    
578 n-ki 613 lseek(handle, offset, SEEK_SET);
579 n-ki 569
580     n = write(handle, data, length);
581    
582     if (n < 0)
583     {
584     perror("write");
585     *result = 0;
586 n-ki 600 switch (errno)
587     {
588     case ENOSPC:
589     return STATUS_DISK_FULL;
590     default:
591     return STATUS_ACCESS_DENIED;
592     }
593 n-ki 569 }
594    
595     *result = n;
596    
597     return STATUS_SUCCESS;
598     }
599    
600     NTSTATUS
601 jsorg71 776 disk_query_information(NTHANDLE handle, uint32 info_class, STREAM out)
602 n-ki 569 {
603     uint32 file_attributes, ft_high, ft_low;
604     struct stat filestat;
605     char *path, *filename;
606    
607     path = g_fileinfo[handle].path;
608    
609 stargo 865 /* Get information about file */
610 n-ki 569 if (fstat(handle, &filestat) != 0)
611     {
612     perror("stat");
613     out_uint8(out, 0);
614     return STATUS_ACCESS_DENIED;
615     }
616    
617 stargo 865 /* Set file attributes */
618 n-ki 569 file_attributes = 0;
619     if (S_ISDIR(filestat.st_mode))
620     file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
621 n-ki 600
622 n-ki 569 filename = 1 + strrchr(path, '/');
623     if (filename && filename[0] == '.')
624     file_attributes |= FILE_ATTRIBUTE_HIDDEN;
625    
626 n-ki 600 if (!file_attributes)
627     file_attributes |= FILE_ATTRIBUTE_NORMAL;
628    
629     if (!(filestat.st_mode & S_IWUSR))
630     file_attributes |= FILE_ATTRIBUTE_READONLY;
631    
632 stargo 865 /* Return requested data */
633 n-ki 569 switch (info_class)
634     {
635 astrand 653 case FileBasicInformation:
636 n-ki 600 seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high,
637     &ft_low);
638 stargo 865 out_uint32_le(out, ft_low); /* create_access_time */
639 n-ki 600 out_uint32_le(out, ft_high);
640 n-ki 569
641     seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low);
642 stargo 865 out_uint32_le(out, ft_low); /* last_access_time */
643 n-ki 569 out_uint32_le(out, ft_high);
644    
645     seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low);
646 stargo 865 out_uint32_le(out, ft_low); /* last_write_time */
647 n-ki 569 out_uint32_le(out, ft_high);
648    
649 n-ki 600 seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low);
650 stargo 865 out_uint32_le(out, ft_low); /* last_change_time */
651 n-ki 600 out_uint32_le(out, ft_high);
652    
653 n-ki 569 out_uint32_le(out, file_attributes);
654     break;
655    
656 astrand 653 case FileStandardInformation:
657 n-ki 569
658 stargo 865 out_uint32_le(out, filestat.st_size); /* Allocation size */
659 n-ki 569 out_uint32_le(out, 0);
660 stargo 865 out_uint32_le(out, filestat.st_size); /* End of file */
661 n-ki 569 out_uint32_le(out, 0);
662 stargo 865 out_uint32_le(out, filestat.st_nlink); /* Number of links */
663     out_uint8(out, 0); /* Delete pending */
664     out_uint8(out, S_ISDIR(filestat.st_mode) ? 1 : 0); /* Directory */
665 n-ki 569 break;
666    
667 astrand 653 case FileObjectIdInformation:
668 n-ki 569
669     out_uint32_le(out, file_attributes); /* File Attributes */
670     out_uint32_le(out, 0); /* Reparse Tag */
671     break;
672    
673     default:
674    
675     unimpl("IRP Query (File) Information class: 0x%x\n", info_class);
676     return STATUS_INVALID_PARAMETER;
677     }
678     return STATUS_SUCCESS;
679     }
680    
681     NTSTATUS
682 jsorg71 776 disk_set_information(NTHANDLE handle, uint32 info_class, STREAM in, STREAM out)
683 n-ki 569 {
684 stargo 795 uint32 length, file_attributes, ft_high, ft_low, delete_on_close;
685 n-ki 569 char newname[256], fullpath[256];
686     struct fileinfo *pfinfo;
687 n-ki 600 int mode;
688     struct stat filestat;
689     time_t write_time, change_time, access_time, mod_time;
690     struct utimbuf tvs;
691 n-ki 612 struct STATFS_T stat_fs;
692 n-ki 600
693 n-ki 569 pfinfo = &(g_fileinfo[handle]);
694 stargo 795 g_notify_stamp = True;
695 n-ki 569
696     switch (info_class)
697     {
698 astrand 653 case FileBasicInformation:
699 n-ki 600 write_time = change_time = access_time = 0;
700 n-ki 569
701 n-ki 600 in_uint8s(in, 4); /* Handle of root dir? */
702     in_uint8s(in, 24); /* unknown */
703    
704 stargo 865 /* CreationTime */
705 n-ki 600 in_uint32_le(in, ft_low);
706     in_uint32_le(in, ft_high);
707    
708 stargo 865 /* AccessTime */
709 n-ki 600 in_uint32_le(in, ft_low);
710     in_uint32_le(in, ft_high);
711     if (ft_low || ft_high)
712     access_time = convert_1970_to_filetime(ft_high, ft_low);
713    
714 stargo 865 /* WriteTime */
715 n-ki 600 in_uint32_le(in, ft_low);
716     in_uint32_le(in, ft_high);
717     if (ft_low || ft_high)
718     write_time = convert_1970_to_filetime(ft_high, ft_low);
719    
720 stargo 865 /* ChangeTime */
721 n-ki 600 in_uint32_le(in, ft_low);
722     in_uint32_le(in, ft_high);
723     if (ft_low || ft_high)
724     change_time = convert_1970_to_filetime(ft_high, ft_low);
725    
726     in_uint32_le(in, file_attributes);
727    
728     if (fstat(handle, &filestat))
729     return STATUS_ACCESS_DENIED;
730    
731     tvs.modtime = filestat.st_mtime;
732     tvs.actime = filestat.st_atime;
733     if (access_time)
734     tvs.actime = access_time;
735    
736    
737     if (write_time || change_time)
738     mod_time = MIN(write_time, change_time);
739     else
740     mod_time = write_time ? write_time : change_time;
741    
742     if (mod_time)
743     tvs.modtime = mod_time;
744    
745    
746     if (access_time || write_time || change_time)
747     {
748     #if WITH_DEBUG_RDP5
749     printf("FileBasicInformation access time %s",
750     ctime(&tvs.actime));
751     printf("FileBasicInformation modification time %s",
752     ctime(&tvs.modtime));
753     #endif
754 stargo 795 if (utime(pfinfo->path, &tvs) && errno != EPERM)
755 n-ki 600 return STATUS_ACCESS_DENIED;
756     }
757    
758     if (!file_attributes)
759 stargo 865 break; /* not valid */
760 n-ki 600
761     mode = filestat.st_mode;
762    
763     if (file_attributes & FILE_ATTRIBUTE_READONLY)
764     mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
765     else
766     mode |= S_IWUSR;
767    
768     mode &= 0777;
769     #if WITH_DEBUG_RDP5
770     printf("FileBasicInformation set access mode 0%o", mode);
771     #endif
772    
773     if (fchmod(handle, mode))
774     return STATUS_ACCESS_DENIED;
775 n-ki 612
776 n-ki 569 break;
777    
778 astrand 653 case FileRenameInformation:
779 n-ki 569
780     in_uint8s(in, 4); /* Handle of root dir? */
781     in_uint8s(in, 0x1a); /* unknown */
782     in_uint32_le(in, length);
783    
784     if (length && (length / 2) < 256)
785     {
786     rdp_in_unistr(in, newname, length);
787     convert_to_unix_filename(newname);
788     }
789     else
790     {
791     return STATUS_INVALID_PARAMETER;
792     }
793    
794     sprintf(fullpath, "%s%s", g_rdpdr_device[pfinfo->device_id].local_path,
795     newname);
796    
797     if (rename(pfinfo->path, fullpath) != 0)
798     {
799     perror("rename");
800     return STATUS_ACCESS_DENIED;
801     }
802     break;
803    
804 astrand 653 case FileDispositionInformation:
805 astrand 659 /* As far as I understand it, the correct
806     thing to do here is to *schedule* a delete,
807     so it will be deleted when the file is
808     closed. Subsequent
809     FileDispositionInformation requests with
810     DeleteFile set to FALSE should unschedule
811     the delete. See
812 stargo 795 http://www.osronline.com/article.cfm?article=245. */
813 n-ki 569
814 stargo 795 in_uint32_le(in, delete_on_close);
815 n-ki 601
816 stargo 795 if (delete_on_close ||
817     (pfinfo->
818     accessmask & (FILE_DELETE_ON_CLOSE | FILE_COMPLETE_IF_OPLOCKED)))
819 n-ki 601 {
820 stargo 795 pfinfo->delete_on_close = True;
821 n-ki 601 }
822    
823 n-ki 569 break;
824    
825 astrand 653 case FileAllocationInformation:
826 astrand 661 /* Fall through to FileEndOfFileInformation,
827     which uses ftrunc. This is like Samba with
828     "strict allocation = false", and means that
829     we won't detect out-of-quota errors, for
830     example. */
831 n-ki 569
832 astrand 653 case FileEndOfFileInformation:
833 n-ki 600 in_uint8s(in, 28); /* unknown */
834     in_uint32_le(in, length); /* file size */
835 n-ki 569
836 n-ki 616 /* 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)
838 stargo 795 if (stat_fs.f_bfree * stat_fs.f_bsize < length)
839 n-ki 616 return STATUS_DISK_FULL;
840    
841 astrand 785 if (ftruncate_growable(handle, length) != 0)
842 astrand 661 {
843     return STATUS_DISK_FULL;
844     }
845    
846 n-ki 569 break;
847     default:
848    
849     unimpl("IRP Set File Information class: 0x%x\n", info_class);
850     return STATUS_INVALID_PARAMETER;
851     }
852     return STATUS_SUCCESS;
853     }
854    
855 stargo 795 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 stargo 873 /*printf("disk_check_notify found changed event\n"); */
877 stargo 795 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 astrand 664 static FsInfoType *
963 n-ki 615 FsVolumeInfo(char *fpath)
964     {
965    
966 stargo 795 static FsInfoType info;
967 stargo 873 #ifdef USE_SETMNTENT
968 stargo 832 FILE *fdfs;
969 n-ki 615 struct mntent *e;
970 stargo 795 #endif
971 n-ki 615
972     /* initialize */
973     memset(&info, 0, sizeof(info));
974     strcpy(info.label, "RDESKTOP");
975     strcpy(info.type, "RDPFS");
976    
977 stargo 873 #ifdef USE_SETMNTENT
978 n-ki 615 fdfs = setmntent(MNTENT_PATH, "r");
979     if (!fdfs)
980     return &info;
981    
982     while ((e = getmntent(fdfs)))
983     {
984     if (strncmp(fpath, e->mnt_dir, strlen(fpath)) == 0)
985     {
986     strcpy(info.type, e->mnt_type);
987     strcpy(info.name, e->mnt_fsname);
988     if (strstr(e->mnt_opts, "vfat") || strstr(e->mnt_opts, "iso9660"))
989     {
990     int fd = open(e->mnt_fsname, O_RDONLY);
991     if (fd >= 0)
992     {
993     unsigned char buf[512];
994     memset(buf, 0, sizeof(buf));
995     if (strstr(e->mnt_opts, "vfat"))
996     /*FAT*/
997     {
998     strcpy(info.type, "vfat");
999     read(fd, buf, sizeof(buf));
1000     info.serial =
1001     (buf[42] << 24) + (buf[41] << 16) +
1002     (buf[40] << 8) + buf[39];
1003     strncpy(info.label, buf + 43, 10);
1004     info.label[10] = '\0';
1005     }
1006     else if (lseek(fd, 32767, SEEK_SET) >= 0) /* ISO9660 */
1007     {
1008     read(fd, buf, sizeof(buf));
1009     strncpy(info.label, buf + 41, 32);
1010     info.label[32] = '\0';
1011 stargo 865 /* info.Serial = (buf[128]<<24)+(buf[127]<<16)+(buf[126]<<8)+buf[125]; */
1012 n-ki 615 }
1013     close(fd);
1014     }
1015     }
1016     }
1017     }
1018     endmntent(fdfs);
1019     #else
1020     /* initialize */
1021     memset(&info, 0, sizeof(info));
1022     strcpy(info.label, "RDESKTOP");
1023     strcpy(info.type, "RDPFS");
1024    
1025     #endif
1026     return &info;
1027     }
1028    
1029    
1030 n-ki 569 NTSTATUS
1031 jsorg71 776 disk_query_volume_information(NTHANDLE handle, uint32 info_class, STREAM out)
1032 n-ki 569 {
1033 stargo 574 struct STATFS_T stat_fs;
1034 n-ki 569 struct fileinfo *pfinfo;
1035 n-ki 615 FsInfoType *fsinfo;
1036 n-ki 569
1037     pfinfo = &(g_fileinfo[handle]);
1038    
1039 n-ki 600 if (STATFS_FN(pfinfo->path, &stat_fs) != 0)
1040 n-ki 569 {
1041     perror("statfs");
1042     return STATUS_ACCESS_DENIED;
1043     }
1044    
1045 n-ki 615 fsinfo = FsVolumeInfo(pfinfo->path);
1046    
1047 n-ki 569 switch (info_class)
1048     {
1049 astrand 653 case FileFsVolumeInformation:
1050 n-ki 569
1051     out_uint32_le(out, 0); /* volume creation time low */
1052     out_uint32_le(out, 0); /* volume creation time high */
1053 n-ki 615 out_uint32_le(out, fsinfo->serial); /* serial */
1054    
1055     out_uint32_le(out, 2 * strlen(fsinfo->label)); /* length of string */
1056    
1057 n-ki 569 out_uint8(out, 0); /* support objects? */
1058 n-ki 615 rdp_out_unistr(out, fsinfo->label, 2 * strlen(fsinfo->label) - 2);
1059 n-ki 569 break;
1060    
1061 astrand 653 case FileFsSizeInformation:
1062 n-ki 569
1063     out_uint32_le(out, stat_fs.f_blocks); /* Total allocation units low */
1064     out_uint32_le(out, 0); /* Total allocation high units */
1065     out_uint32_le(out, stat_fs.f_bfree); /* Available allocation units */
1066     out_uint32_le(out, 0); /* Available allowcation units */
1067     out_uint32_le(out, stat_fs.f_bsize / 0x200); /* Sectors per allocation unit */
1068     out_uint32_le(out, 0x200); /* Bytes per sector */
1069     break;
1070    
1071 astrand 653 case FileFsAttributeInformation:
1072 n-ki 569
1073     out_uint32_le(out, FS_CASE_SENSITIVE | FS_CASE_IS_PRESERVED); /* fs attributes */
1074 stargo 574 out_uint32_le(out, F_NAMELEN(stat_fs)); /* max length of filename */
1075 n-ki 615
1076     out_uint32_le(out, 2 * strlen(fsinfo->type)); /* length of fs_type */
1077     rdp_out_unistr(out, fsinfo->type, 2 * strlen(fsinfo->type) - 2);
1078 n-ki 569 break;
1079    
1080 astrand 653 case FileFsLabelInformation:
1081     case FileFsDeviceInformation:
1082     case FileFsControlInformation:
1083     case FileFsFullSizeInformation:
1084     case FileFsObjectIdInformation:
1085     case FileFsMaximumInformation:
1086    
1087 n-ki 569 default:
1088    
1089     unimpl("IRP Query Volume Information class: 0x%x\n", info_class);
1090     return STATUS_INVALID_PARAMETER;
1091     }
1092     return STATUS_SUCCESS;
1093     }
1094    
1095     NTSTATUS
1096 jsorg71 776 disk_query_directory(NTHANDLE handle, uint32 info_class, char *pattern, STREAM out)
1097 n-ki 569 {
1098     uint32 file_attributes, ft_low, ft_high;
1099     char *dirname, fullpath[256];
1100     DIR *pdir;
1101     struct dirent *pdirent;
1102     struct stat fstat;
1103     struct fileinfo *pfinfo;
1104    
1105     pfinfo = &(g_fileinfo[handle]);
1106     pdir = pfinfo->pdir;
1107     dirname = pfinfo->path;
1108     file_attributes = 0;
1109    
1110     switch (info_class)
1111     {
1112 astrand 696 case FileBothDirectoryInformation:
1113 n-ki 569
1114 stargo 865 /* If a search pattern is received, remember this pattern, and restart search */
1115 n-ki 569 if (pattern[0] != 0)
1116     {
1117     strncpy(pfinfo->pattern, 1 + strrchr(pattern, '/'), 64);
1118     rewinddir(pdir);
1119     }
1120    
1121 stargo 865 /* find next dirent matching pattern */
1122 n-ki 569 pdirent = readdir(pdir);
1123     while (pdirent && fnmatch(pfinfo->pattern, pdirent->d_name, 0) != 0)
1124     pdirent = readdir(pdir);
1125    
1126     if (pdirent == NULL)
1127     return STATUS_NO_MORE_FILES;
1128    
1129 stargo 865 /* Get information for directory entry */
1130 n-ki 569 sprintf(fullpath, "%s/%s", dirname, pdirent->d_name);
1131 n-ki 600
1132 n-ki 569 if (stat(fullpath, &fstat))
1133     {
1134 astrand 698 switch (errno)
1135     {
1136     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 n-ki 569 }
1150    
1151     if (S_ISDIR(fstat.st_mode))
1152     file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
1153     if (pdirent->d_name[0] == '.')
1154     file_attributes |= FILE_ATTRIBUTE_HIDDEN;
1155 n-ki 600 if (!file_attributes)
1156     file_attributes |= FILE_ATTRIBUTE_NORMAL;
1157     if (!(fstat.st_mode & S_IWUSR))
1158     file_attributes |= FILE_ATTRIBUTE_READONLY;
1159 n-ki 569
1160 stargo 865 /* Return requested information */
1161     out_uint8s(out, 8); /* unknown zero */
1162 n-ki 569
1163 n-ki 600 seconds_since_1970_to_filetime(get_create_time(&fstat), &ft_high, &ft_low);
1164 stargo 865 out_uint32_le(out, ft_low); /* create time */
1165 n-ki 600 out_uint32_le(out, ft_high);
1166    
1167 n-ki 569 seconds_since_1970_to_filetime(fstat.st_atime, &ft_high, &ft_low);
1168 stargo 865 out_uint32_le(out, ft_low); /* last_access_time */
1169 n-ki 569 out_uint32_le(out, ft_high);
1170    
1171     seconds_since_1970_to_filetime(fstat.st_mtime, &ft_high, &ft_low);
1172 stargo 865 out_uint32_le(out, ft_low); /* last_write_time */
1173 n-ki 569 out_uint32_le(out, ft_high);
1174    
1175 n-ki 600 seconds_since_1970_to_filetime(fstat.st_ctime, &ft_high, &ft_low);
1176 stargo 865 out_uint32_le(out, ft_low); /* change_write_time */
1177 n-ki 600 out_uint32_le(out, ft_high);
1178    
1179 stargo 865 out_uint32_le(out, fstat.st_size); /* filesize low */
1180     out_uint32_le(out, 0); /* filesize high */
1181     out_uint32_le(out, fstat.st_size); /* filesize low */
1182     out_uint32_le(out, 0); /* filesize high */
1183 n-ki 569 out_uint32_le(out, file_attributes);
1184 stargo 865 out_uint8(out, 2 * strlen(pdirent->d_name) + 2); /* unicode length */
1185     out_uint8s(out, 7); /* pad? */
1186     out_uint8(out, 0); /* 8.3 file length */
1187     out_uint8s(out, 2 * 12); /* 8.3 unicode length */
1188 n-ki 569 rdp_out_unistr(out, pdirent->d_name, 2 * strlen(pdirent->d_name));
1189     break;
1190    
1191     default:
1192 astrand 696 /* FIXME: Support FileDirectoryInformation,
1193     FileFullDirectoryInformation, and
1194     FileNamesInformation */
1195 n-ki 569
1196     unimpl("IRP Query Directory sub: 0x%x\n", info_class);
1197     return STATUS_INVALID_PARAMETER;
1198     }
1199    
1200     return STATUS_SUCCESS;
1201     }
1202    
1203 n-ki 600
1204    
1205     static NTSTATUS
1206 jsorg71 776 disk_device_control(NTHANDLE handle, uint32 request, STREAM in, STREAM out)
1207 n-ki 600 {
1208     if (((request >> 16) != 20) || ((request >> 16) != 9))
1209     return STATUS_INVALID_PARAMETER;
1210    
1211     /* extract operation */
1212     request >>= 2;
1213     request &= 0xfff;
1214    
1215     printf("DISK IOCTL %d\n", request);
1216    
1217     switch (request)
1218     {
1219 stargo 865 case 25: /* ? */
1220     case 42: /* ? */
1221 n-ki 600 default:
1222     unimpl("DISK IOCTL %d\n", request);
1223     return STATUS_INVALID_PARAMETER;
1224     }
1225    
1226     return STATUS_SUCCESS;
1227     }
1228    
1229 n-ki 569 DEVICE_FNS disk_fns = {
1230     disk_create,
1231     disk_close,
1232     disk_read,
1233     disk_write,
1234 n-ki 600 disk_device_control /* device_control */
1235 n-ki 569 };

  ViewVC Help
Powered by ViewVC 1.1.26