/[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 875 - (hide annotations)
Sat Apr 2 17:49:56 2005 UTC (19 years, 1 month ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/disk.c
File MIME type: text/plain
File size: 28375 byte(s)
fix dummy_statfs

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

  ViewVC Help
Powered by ViewVC 1.1.26