/[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 879 - (hide annotations)
Sun Apr 3 18:08:05 2005 UTC (19 years, 2 months ago) by astrand
File MIME type: text/plain
File size: 28385 byte(s)
Indent fixes

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

  ViewVC Help
Powered by ViewVC 1.1.26