/[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 613 - (hide annotations)
Mon Feb 23 10:34:18 2004 UTC (20 years, 3 months ago) by n-ki
File MIME type: text/plain
File size: 21962 byte(s)
correct handling of offset - partial merge from volker mildes patch. at date only disk.c uses offset, so there wont be any problem.

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     #define FILE_ATTRIBUTE_READONLY 0x00000001
22     #define FILE_ATTRIBUTE_HIDDEN 0x00000002
23     #define FILE_ATTRIBUTE_SYSTEM 0x00000004
24     #define FILE_ATTRIBUTE_DIRECTORY 0x00000010
25     #define FILE_ATTRIBUTE_ARCHIVE 0x00000020
26     #define FILE_ATTRIBUTE_DEVICE 0x00000040
27 n-ki 597 #define FILE_ATTRIBUTE_UNKNOWNXXX0 0x00000060 /* ??? ACTION i.e. 0x860 == compress this file ? */
28 n-ki 569 #define FILE_ATTRIBUTE_NORMAL 0x00000080
29     #define FILE_ATTRIBUTE_TEMPORARY 0x00000100
30     #define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
31     #define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
32     #define FILE_ATTRIBUTE_COMPRESSED 0x00000800
33     #define FILE_ATTRIBUTE_OFFLINE 0x00001000
34     #define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
35     #define FILE_ATTRIBUTE_ENCRYPTED 0x00004000
36    
37 n-ki 597 #define FILE_FLAG_OPEN_NO_RECALL 0x00100000
38     #define FILE_FLAG_OPEN_REPARSE_POINT 0x00200000
39     #define FILE_FLAG_POSIX_SEMANTICS 0x01000000
40     #define FILE_FLAG_BACKUP_SEMANTICS 0x02000000 /* sometimes used to create a directory */
41     #define FILE_FLAG_DELETE_ON_CLOSE 0x04000000
42     #define FILE_FLAG_SEQUENTIAL_SCAN 0x08000000
43     #define FILE_FLAG_RANDOM_ACCESS 0x10000000
44     #define FILE_FLAG_NO_BUFFERING 0x20000000
45     #define FILE_FLAG_OVERLAPPED 0x40000000
46     #define FILE_FLAG_WRITE_THROUGH 0x80000000
47    
48     #define FILE_SHARE_READ 0x01
49     #define FILE_SHARE_WRITE 0x02
50     #define FILE_SHARE_DELETE 0x04
51    
52 n-ki 569 #define FILE_BASIC_INFORMATION 0x04
53     #define FILE_STANDARD_INFORMATION 0x05
54    
55     #define FS_CASE_SENSITIVE 0x00000001
56     #define FS_CASE_IS_PRESERVED 0x00000002
57     #define FS_UNICODE_STORED_ON_DISK 0x00000004
58     #define FS_PERSISTENT_ACLS 0x00000008
59     #define FS_FILE_COMPRESSION 0x00000010
60     #define FS_VOLUME_QUOTAS 0x00000020
61     #define FS_SUPPORTS_SPARSE_FILES 0x00000040
62     #define FS_SUPPORTS_REPARSE_POINTS 0x00000080
63     #define FS_SUPPORTS_REMOTE_STORAGE 0X00000100
64     #define FS_VOL_IS_COMPRESSED 0x00008000
65     #define FILE_READ_ONLY_VOLUME 0x00080000
66    
67     #define OPEN_EXISTING 1
68     #define CREATE_NEW 2
69     #define OPEN_ALWAYS 3
70     #define TRUNCATE_EXISTING 4
71     #define CREATE_ALWAYS 5
72    
73     #define GENERIC_READ 0x80000000
74     #define GENERIC_WRITE 0x40000000
75     #define GENERIC_EXECUTE 0x20000000
76     #define GENERIC_ALL 0x10000000
77    
78     #define ERROR_FILE_NOT_FOUND 2L
79     #define ERROR_ALREADY_EXISTS 183L
80    
81     #define MAX_OPEN_FILES 0x100
82    
83 stargo 572 #if (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
84     #define SOLARIS
85     #endif
86    
87 stargo 603 #if (defined(SOLARIS) || defined(__hpux))
88 stargo 572 #define DIRFD(a) ((a)->dd_fd)
89     #else
90     #define DIRFD(a) (dirfd(a))
91     #endif
92    
93 n-ki 569 #include <sys/types.h>
94     #include <sys/stat.h>
95     #include <unistd.h>
96     #include <fcntl.h> /* open, close */
97     #include <dirent.h> /* opendir, closedir, readdir */
98     #include <fnmatch.h>
99     #include <errno.h> /* errno */
100 stargo 572
101 n-ki 600 #include <utime.h>
102     #include <time.h> /* ctime */
103    
104    
105 stargo 603 #if (defined(SOLARIS) || defined (__hpux) || defined(__BEOS__))
106 stargo 572 #include <sys/statvfs.h> /* solaris statvfs */
107 stargo 574 #define STATFS_FN(path, buf) (statvfs(path,buf))
108     #define STATFS_T statvfs
109 stargo 573 #define F_NAMELEN(buf) ((buf).f_namemax)
110    
111 stargo 576 #elif (defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__))
112 stargo 573 #include <sys/param.h>
113     #include <sys/mount.h>
114 stargo 574 #define STATFS_FN(path, buf) (statfs(path,buf))
115     #define STATFS_T statfs
116 stargo 573 #define F_NAMELEN(buf) (NAME_MAX)
117    
118 stargo 572 #else
119     #include <sys/vfs.h> /* linux statfs */
120 stargo 574 #define STATFS_FN(path, buf) (statfs(path,buf))
121     #define STATFS_T statfs
122 stargo 573 #define F_NAMELEN(buf) ((buf).f_namelen)
123 stargo 572 #endif
124    
125 n-ki 569 #include "rdesktop.h"
126    
127     extern RDPDR_DEVICE g_rdpdr_device[];
128    
129     struct fileinfo
130     {
131     uint32 device_id, flags_and_attributes;
132     char path[256];
133     DIR *pdir;
134     struct dirent *pdirent;
135     char pattern[64];
136     BOOL delete_on_close;
137     }
138     g_fileinfo[MAX_OPEN_FILES];
139    
140 n-ki 600 time_t
141     get_create_time(struct stat *st)
142     {
143     time_t ret, ret1;
144    
145     ret = MIN(st->st_ctime, st->st_mtime);
146     ret1 = MIN(ret, st->st_atime);
147    
148     if (ret1 != (time_t) 0)
149     return ret1;
150    
151     return ret;
152     }
153    
154 n-ki 569 /* Convert seconds since 1970 to a filetime */
155     void
156     seconds_since_1970_to_filetime(time_t seconds, uint32 * high, uint32 * low)
157     {
158     unsigned long long ticks;
159    
160     ticks = (seconds + 11644473600LL) * 10000000;
161     *low = (uint32) ticks;
162     *high = (uint32) (ticks >> 32);
163     }
164    
165 n-ki 600 /* Convert seconds since 1970 back to filetime */
166     time_t
167     convert_1970_to_filetime(uint32 high, uint32 low)
168     {
169     unsigned long long ticks;
170     time_t val;
171    
172     ticks = low + (((unsigned long long) high) << 32);
173     ticks /= 10000000;
174     ticks -= 11644473600LL;
175    
176     val = (time_t) ticks;
177     return (val);
178    
179     }
180    
181    
182 n-ki 569 /* Enumeration of devices from rdesktop.c */
183     /* returns numer of units found and initialized. */
184 n-ki 612 /* optarg looks like ':h=/mnt/floppy,b=/mnt/usbdevice1' */
185 n-ki 569 /* when it arrives to this function. */
186     int
187 astrand 608 disk_enum_devices(uint32 * id, char *optarg)
188 n-ki 569 {
189     char *pos = optarg;
190     char *pos2;
191     int count = 0;
192    
193     // skip the first colon
194     optarg++;
195     while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
196     {
197     pos2 = next_arg(optarg, '=');
198     strcpy(g_rdpdr_device[*id].name, optarg);
199    
200 stargo 570 toupper_str(g_rdpdr_device[*id].name);
201 n-ki 569
202     /* add trailing colon to name. */
203     strcat(g_rdpdr_device[*id].name, ":");
204    
205     g_rdpdr_device[*id].local_path = xmalloc(strlen(pos2) + 1);
206     strcpy(g_rdpdr_device[*id].local_path, pos2);
207     printf("DISK %s to %s\n", g_rdpdr_device[*id].name, g_rdpdr_device[*id].local_path);
208     g_rdpdr_device[*id].device_type = DEVICE_TYPE_DISK;
209     count++;
210     (*id)++;
211    
212     optarg = pos;
213     }
214     return count;
215     }
216    
217 n-ki 596 /* Opens or creates a file or directory */
218 n-ki 569 NTSTATUS
219     disk_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition,
220     uint32 flags_and_attributes, char *filename, HANDLE * phandle)
221     {
222     HANDLE handle;
223     DIR *dirp;
224     int flags, mode;
225     char path[256];
226 n-ki 600 struct stat filestat;
227 n-ki 569
228     handle = 0;
229     dirp = NULL;
230     flags = 0;
231     mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
232    
233 n-ki 600
234 n-ki 569 if (filename[strlen(filename) - 1] == '/')
235     filename[strlen(filename) - 1] = 0;
236     sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename);
237    
238     switch (create_disposition)
239     {
240     case CREATE_ALWAYS:
241    
242     // Delete existing file/link.
243     unlink(path);
244     flags |= O_CREAT;
245     break;
246    
247     case CREATE_NEW:
248    
249     // If the file already exists, then fail.
250     flags |= O_CREAT | O_EXCL;
251     break;
252    
253     case OPEN_ALWAYS:
254    
255     // Create if not already exists.
256     flags |= O_CREAT;
257     break;
258    
259     case OPEN_EXISTING:
260    
261     // Default behaviour
262     break;
263    
264     case TRUNCATE_EXISTING:
265    
266     // If the file does not exist, then fail.
267     flags |= O_TRUNC;
268     break;
269     }
270    
271 n-ki 597 //printf("Open: \"%s\" flags: %u, accessmask: %u sharemode: %u create disp: %u\n", path, flags_and_attributes, accessmask, sharemode, create_disposition);
272    
273     // Get information about file and set that flag ourselfs
274     if ((stat(path, &filestat) == 0) && (S_ISDIR(filestat.st_mode)))
275 n-ki 600 {
276     if (flags_and_attributes & FILE_NON_DIRECTORY_FILE)
277     return STATUS_FILE_IS_A_DIRECTORY;
278     else
279     flags_and_attributes |= FILE_DIRECTORY_FILE;
280     }
281 n-ki 597
282     if (flags_and_attributes & FILE_DIRECTORY_FILE)
283 n-ki 569 {
284 n-ki 597 if (flags & O_CREAT)
285 n-ki 569 {
286 n-ki 597 mkdir(path, mode);
287 n-ki 569 }
288    
289 n-ki 597 dirp = opendir(path);
290     if (!dirp)
291 n-ki 569 {
292     switch (errno)
293     {
294     case EACCES:
295    
296     return STATUS_ACCESS_DENIED;
297    
298     case ENOENT:
299    
300     return STATUS_NO_SUCH_FILE;
301    
302     default:
303    
304 n-ki 597 perror("opendir");
305 n-ki 569 return STATUS_NO_SUCH_FILE;
306     }
307     }
308 n-ki 597 handle = DIRFD(dirp);
309 n-ki 569 }
310 n-ki 597 else
311 n-ki 569 {
312 n-ki 596
313 n-ki 597 if (accessmask & GENERIC_ALL
314     || (accessmask & GENERIC_READ && accessmask & GENERIC_WRITE))
315 n-ki 569 {
316 n-ki 597 flags |= O_RDWR;
317 n-ki 569 }
318 n-ki 597 else if ((accessmask & GENERIC_WRITE) && !(accessmask & GENERIC_READ))
319 n-ki 569 {
320 n-ki 597 flags |= O_WRONLY;
321 n-ki 569 }
322 n-ki 597 else
323     {
324     flags |= O_RDONLY;
325     }
326 n-ki 569
327 n-ki 597 handle = open(path, flags, mode);
328     if (handle == -1)
329 n-ki 569 {
330     switch (errno)
331     {
332 n-ki 600 case EISDIR:
333    
334     return STATUS_FILE_IS_A_DIRECTORY;
335    
336 n-ki 569 case EACCES:
337    
338     return STATUS_ACCESS_DENIED;
339    
340     case ENOENT:
341    
342     return STATUS_NO_SUCH_FILE;
343 n-ki 612 case EEXIST:
344    
345     return STATUS_OBJECT_NAME_COLLISION;
346 n-ki 569 default:
347    
348 n-ki 597 perror("open");
349 n-ki 569 return STATUS_NO_SUCH_FILE;
350     }
351     }
352 n-ki 597
353     /* all read and writes of files should be non blocking */
354     if (fcntl(handle, F_SETFL, O_NONBLOCK) == -1)
355     perror("fcntl");
356 n-ki 569 }
357    
358     if (handle >= MAX_OPEN_FILES)
359     {
360     error("Maximum number of open files (%s) reached. Increase MAX_OPEN_FILES!\n",
361     handle);
362     exit(1);
363     }
364    
365     if (dirp)
366     g_fileinfo[handle].pdir = dirp;
367     g_fileinfo[handle].device_id = device_id;
368     g_fileinfo[handle].flags_and_attributes = flags_and_attributes;
369     strncpy(g_fileinfo[handle].path, path, 255);
370    
371     *phandle = handle;
372     return STATUS_SUCCESS;
373     }
374    
375     NTSTATUS
376     disk_close(HANDLE handle)
377     {
378     struct fileinfo *pfinfo;
379    
380     pfinfo = &(g_fileinfo[handle]);
381    
382     if (pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE)
383     {
384     closedir(pfinfo->pdir);
385     //FIXME: Should check exit code
386     }
387     else
388     {
389     close(handle);
390     }
391    
392     return STATUS_SUCCESS;
393     }
394    
395     NTSTATUS
396     disk_read(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
397     {
398     int n;
399    
400 n-ki 600 #if 0
401 n-ki 596 /* browsing dir ???? */
402     /* each request is 24 bytes */
403     if (g_fileinfo[handle].flags_and_attributes & FILE_DIRECTORY_FILE)
404     {
405     *result = 0;
406     return STATUS_SUCCESS;
407     }
408 n-ki 600 #endif
409 n-ki 596
410 n-ki 613 lseek(handle, offset, SEEK_SET);
411    
412 n-ki 569 n = read(handle, data, length);
413    
414     if (n < 0)
415     {
416     *result = 0;
417 n-ki 600 switch (errno)
418     {
419     case EISDIR:
420     return STATUS_FILE_IS_A_DIRECTORY;
421     default:
422     perror("read");
423     return STATUS_INVALID_PARAMETER;
424     }
425 n-ki 569 }
426    
427     *result = n;
428    
429     return STATUS_SUCCESS;
430     }
431    
432     NTSTATUS
433     disk_write(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
434     {
435     int n;
436    
437 n-ki 613 lseek(handle, offset, SEEK_SET);
438 n-ki 569
439     n = write(handle, data, length);
440    
441     if (n < 0)
442     {
443     perror("write");
444     *result = 0;
445 n-ki 600 switch (errno)
446     {
447     case ENOSPC:
448     return STATUS_DISK_FULL;
449     default:
450     return STATUS_ACCESS_DENIED;
451     }
452 n-ki 569 }
453    
454     *result = n;
455    
456     return STATUS_SUCCESS;
457     }
458    
459     NTSTATUS
460     disk_query_information(HANDLE handle, uint32 info_class, STREAM out)
461     {
462     uint32 file_attributes, ft_high, ft_low;
463     struct stat filestat;
464     char *path, *filename;
465    
466     path = g_fileinfo[handle].path;
467    
468     // Get information about file
469     if (fstat(handle, &filestat) != 0)
470     {
471     perror("stat");
472     out_uint8(out, 0);
473     return STATUS_ACCESS_DENIED;
474     }
475    
476     // Set file attributes
477     file_attributes = 0;
478     if (S_ISDIR(filestat.st_mode))
479     file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
480 n-ki 600
481 n-ki 569 filename = 1 + strrchr(path, '/');
482     if (filename && filename[0] == '.')
483     file_attributes |= FILE_ATTRIBUTE_HIDDEN;
484    
485 n-ki 600 if (!file_attributes)
486     file_attributes |= FILE_ATTRIBUTE_NORMAL;
487    
488     if (!(filestat.st_mode & S_IWUSR))
489     file_attributes |= FILE_ATTRIBUTE_READONLY;
490    
491 n-ki 569 // Return requested data
492     switch (info_class)
493     {
494     case 4: /* FileBasicInformation */
495 n-ki 600 seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high,
496     &ft_low);
497     out_uint32_le(out, ft_low); //create_access_time
498     out_uint32_le(out, ft_high);
499 n-ki 569
500     seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low);
501     out_uint32_le(out, ft_low); //last_access_time
502     out_uint32_le(out, ft_high);
503    
504     seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low);
505     out_uint32_le(out, ft_low); //last_write_time
506     out_uint32_le(out, ft_high);
507    
508 n-ki 600 seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low);
509     out_uint32_le(out, ft_low); //last_change_time
510     out_uint32_le(out, ft_high);
511    
512 n-ki 569 out_uint32_le(out, file_attributes);
513     break;
514    
515     case 5: /* FileStandardInformation */
516    
517     out_uint32_le(out, filestat.st_size); //Allocation size
518     out_uint32_le(out, 0);
519     out_uint32_le(out, filestat.st_size); //End of file
520     out_uint32_le(out, 0);
521     out_uint32_le(out, filestat.st_nlink); //Number of links
522     out_uint8(out, 0); //Delete pending
523     out_uint8(out, S_ISDIR(filestat.st_mode) ? 1 : 0); //Directory
524     break;
525    
526     case 35: /* FileObjectIdInformation */
527    
528     out_uint32_le(out, file_attributes); /* File Attributes */
529     out_uint32_le(out, 0); /* Reparse Tag */
530     break;
531    
532     default:
533    
534     unimpl("IRP Query (File) Information class: 0x%x\n", info_class);
535     return STATUS_INVALID_PARAMETER;
536     }
537     return STATUS_SUCCESS;
538     }
539    
540     NTSTATUS
541     disk_set_information(HANDLE handle, uint32 info_class, STREAM in, STREAM out)
542     {
543     uint32 device_id, length, file_attributes, ft_high, ft_low;
544     char newname[256], fullpath[256];
545     struct fileinfo *pfinfo;
546    
547 n-ki 600 int mode;
548     struct stat filestat;
549     time_t write_time, change_time, access_time, mod_time;
550     struct utimbuf tvs;
551 n-ki 612 struct STATFS_T stat_fs;
552 n-ki 600
553 n-ki 569 pfinfo = &(g_fileinfo[handle]);
554    
555     switch (info_class)
556     {
557     case 4: /* FileBasicInformation */
558 n-ki 600 write_time = change_time = access_time = 0;
559 n-ki 569
560 n-ki 600 in_uint8s(in, 4); /* Handle of root dir? */
561     in_uint8s(in, 24); /* unknown */
562    
563     // CreationTime
564     in_uint32_le(in, ft_low);
565     in_uint32_le(in, ft_high);
566    
567     // AccessTime
568     in_uint32_le(in, ft_low);
569     in_uint32_le(in, ft_high);
570     if (ft_low || ft_high)
571     access_time = convert_1970_to_filetime(ft_high, ft_low);
572    
573     // WriteTime
574     in_uint32_le(in, ft_low);
575     in_uint32_le(in, ft_high);
576     if (ft_low || ft_high)
577     write_time = convert_1970_to_filetime(ft_high, ft_low);
578    
579     // ChangeTime
580     in_uint32_le(in, ft_low);
581     in_uint32_le(in, ft_high);
582     if (ft_low || ft_high)
583     change_time = convert_1970_to_filetime(ft_high, ft_low);
584    
585     in_uint32_le(in, file_attributes);
586    
587     if (fstat(handle, &filestat))
588     return STATUS_ACCESS_DENIED;
589    
590     tvs.modtime = filestat.st_mtime;
591     tvs.actime = filestat.st_atime;
592     if (access_time)
593     tvs.actime = access_time;
594    
595    
596     if (write_time || change_time)
597     mod_time = MIN(write_time, change_time);
598     else
599     mod_time = write_time ? write_time : change_time;
600    
601     if (mod_time)
602     tvs.modtime = mod_time;
603    
604    
605     if (access_time || write_time || change_time)
606     {
607     #if WITH_DEBUG_RDP5
608     printf("FileBasicInformation access time %s",
609     ctime(&tvs.actime));
610     printf("FileBasicInformation modification time %s",
611     ctime(&tvs.modtime));
612     #endif
613     if (utime(pfinfo->path, &tvs))
614     return STATUS_ACCESS_DENIED;
615     }
616    
617     if (!file_attributes)
618     break; // not valid
619    
620     mode = filestat.st_mode;
621    
622     if (file_attributes & FILE_ATTRIBUTE_READONLY)
623     mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
624     else
625     mode |= S_IWUSR;
626    
627     mode &= 0777;
628     #if WITH_DEBUG_RDP5
629     printf("FileBasicInformation set access mode 0%o", mode);
630     #endif
631    
632     if (fchmod(handle, mode))
633     return STATUS_ACCESS_DENIED;
634 n-ki 612
635     /* prevents start of writing if not enough space left on device */
636     if (STATFS_FN(g_rdpdr_device[pfinfo->device_id].local_path, &stat_fs) == 0)
637     if (stat_fs.f_bsize * stat_fs.f_bfree < length)
638     return STATUS_DISK_FULL;
639    
640 n-ki 569 break;
641    
642     case 10: /* FileRenameInformation */
643    
644     in_uint8s(in, 4); /* Handle of root dir? */
645     in_uint8s(in, 0x1a); /* unknown */
646     in_uint32_le(in, length);
647    
648     if (length && (length / 2) < 256)
649     {
650     rdp_in_unistr(in, newname, length);
651     convert_to_unix_filename(newname);
652     }
653     else
654     {
655     return STATUS_INVALID_PARAMETER;
656     }
657    
658     sprintf(fullpath, "%s%s", g_rdpdr_device[pfinfo->device_id].local_path,
659     newname);
660    
661     if (rename(pfinfo->path, fullpath) != 0)
662     {
663     perror("rename");
664     return STATUS_ACCESS_DENIED;
665     }
666     break;
667    
668     case 13: /* FileDispositionInformation */
669    
670     //unimpl("IRP Set File Information class: FileDispositionInformation\n");
671 n-ki 601
672     //in_uint32_le(in, delete_on_close);
673 n-ki 569 // disk_close(handle);
674 n-ki 601 if ((pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE)) // remove a directory
675     {
676     if (rmdir(pfinfo->path) < 0)
677     return STATUS_ACCESS_DENIED;
678     }
679     else if (unlink(pfinfo->path) < 0) // unlink a file
680     return STATUS_ACCESS_DENIED;
681    
682 n-ki 569 break;
683    
684     case 19: /* FileAllocationInformation */
685    
686     unimpl("IRP Set File Information class: FileAllocationInformation\n");
687     break;
688    
689     case 20: /* FileEndOfFileInformation */
690 n-ki 600 in_uint8s(in, 28); /* unknown */
691     in_uint32_le(in, length); /* file size */
692 n-ki 569
693 n-ki 600 printf("FileEndOfFileInformation length = %d\n", length);
694     // ????????????
695    
696 n-ki 569 unimpl("IRP Set File Information class: FileEndOfFileInformation\n");
697     break;
698     default:
699    
700     unimpl("IRP Set File Information class: 0x%x\n", info_class);
701     return STATUS_INVALID_PARAMETER;
702     }
703     return STATUS_SUCCESS;
704     }
705    
706     NTSTATUS
707     disk_query_volume_information(HANDLE handle, uint32 info_class, STREAM out)
708     {
709     char *volume, *fs_type;
710 stargo 574 struct STATFS_T stat_fs;
711 n-ki 569 struct fileinfo *pfinfo;
712    
713     pfinfo = &(g_fileinfo[handle]);
714     volume = "RDESKTOP";
715     fs_type = "RDPFS";
716    
717 n-ki 600 if (STATFS_FN(pfinfo->path, &stat_fs) != 0)
718 n-ki 569 {
719     perror("statfs");
720     return STATUS_ACCESS_DENIED;
721     }
722    
723     switch (info_class)
724     {
725     case 1: /* FileFsVolumeInformation */
726    
727     out_uint32_le(out, 0); /* volume creation time low */
728     out_uint32_le(out, 0); /* volume creation time high */
729     out_uint32_le(out, 0); /* serial */
730     out_uint32_le(out, 2 * strlen(volume)); /* length of string */
731     out_uint8(out, 0); /* support objects? */
732     rdp_out_unistr(out, volume, 2 * strlen(volume) - 2);
733     break;
734    
735     case 3: /* FileFsSizeInformation */
736    
737     out_uint32_le(out, stat_fs.f_blocks); /* Total allocation units low */
738     out_uint32_le(out, 0); /* Total allocation high units */
739     out_uint32_le(out, stat_fs.f_bfree); /* Available allocation units */
740     out_uint32_le(out, 0); /* Available allowcation units */
741     out_uint32_le(out, stat_fs.f_bsize / 0x200); /* Sectors per allocation unit */
742     out_uint32_le(out, 0x200); /* Bytes per sector */
743     break;
744    
745     case 5: /* FileFsAttributeInformation */
746    
747     out_uint32_le(out, FS_CASE_SENSITIVE | FS_CASE_IS_PRESERVED); /* fs attributes */
748 stargo 574 out_uint32_le(out, F_NAMELEN(stat_fs)); /* max length of filename */
749 n-ki 569 out_uint32_le(out, 2 * strlen(fs_type)); /* length of fs_type */
750     rdp_out_unistr(out, fs_type, 2 * strlen(fs_type) - 2);
751     break;
752    
753     case 2: /* FileFsLabelInformation */
754     case 4: /* FileFsDeviceInformation */
755     case 6: /* FileFsControlInformation */
756     case 7: /* FileFsFullSizeInformation */
757     case 8: /* FileFsObjectIdInformation */
758     case 9: /* FileFsMaximumInformation */
759     default:
760    
761     unimpl("IRP Query Volume Information class: 0x%x\n", info_class);
762     return STATUS_INVALID_PARAMETER;
763     }
764     return STATUS_SUCCESS;
765     }
766    
767     NTSTATUS
768     disk_query_directory(HANDLE handle, uint32 info_class, char *pattern, STREAM out)
769     {
770     uint32 file_attributes, ft_low, ft_high;
771     char *dirname, fullpath[256];
772     DIR *pdir;
773     struct dirent *pdirent;
774     struct stat fstat;
775     struct fileinfo *pfinfo;
776    
777     pfinfo = &(g_fileinfo[handle]);
778     pdir = pfinfo->pdir;
779     dirname = pfinfo->path;
780     file_attributes = 0;
781    
782     switch (info_class)
783     {
784     case 3: //FIXME: Why 3?
785    
786     // If a search pattern is received, remember this pattern, and restart search
787     if (pattern[0] != 0)
788     {
789     strncpy(pfinfo->pattern, 1 + strrchr(pattern, '/'), 64);
790     rewinddir(pdir);
791     }
792    
793     // find next dirent matching pattern
794     pdirent = readdir(pdir);
795     while (pdirent && fnmatch(pfinfo->pattern, pdirent->d_name, 0) != 0)
796     pdirent = readdir(pdir);
797    
798     if (pdirent == NULL)
799     return STATUS_NO_MORE_FILES;
800    
801     // Get information for directory entry
802     sprintf(fullpath, "%s/%s", dirname, pdirent->d_name);
803 n-ki 600
804 n-ki 596 /* JIF
805 n-ki 569 printf("Stat: %s\n", fullpath); */
806     if (stat(fullpath, &fstat))
807     {
808     perror("stat");
809     out_uint8(out, 0);
810     return STATUS_ACCESS_DENIED;
811     }
812    
813     if (S_ISDIR(fstat.st_mode))
814     file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
815     if (pdirent->d_name[0] == '.')
816     file_attributes |= FILE_ATTRIBUTE_HIDDEN;
817 n-ki 600 if (!file_attributes)
818     file_attributes |= FILE_ATTRIBUTE_NORMAL;
819     if (!(fstat.st_mode & S_IWUSR))
820     file_attributes |= FILE_ATTRIBUTE_READONLY;
821 n-ki 569
822     // Return requested information
823     out_uint8s(out, 8); //unknown zero
824    
825 n-ki 600 seconds_since_1970_to_filetime(get_create_time(&fstat), &ft_high, &ft_low);
826     out_uint32_le(out, ft_low); // create time
827     out_uint32_le(out, ft_high);
828    
829 n-ki 569 seconds_since_1970_to_filetime(fstat.st_atime, &ft_high, &ft_low);
830     out_uint32_le(out, ft_low); //last_access_time
831     out_uint32_le(out, ft_high);
832    
833     seconds_since_1970_to_filetime(fstat.st_mtime, &ft_high, &ft_low);
834     out_uint32_le(out, ft_low); //last_write_time
835     out_uint32_le(out, ft_high);
836    
837 n-ki 600 seconds_since_1970_to_filetime(fstat.st_ctime, &ft_high, &ft_low);
838     out_uint32_le(out, ft_low); //change_write_time
839     out_uint32_le(out, ft_high);
840    
841 n-ki 569 out_uint32_le(out, fstat.st_size); //filesize low
842     out_uint32_le(out, 0); //filesize high
843     out_uint32_le(out, fstat.st_size); //filesize low
844     out_uint32_le(out, 0); //filesize high
845     out_uint32_le(out, file_attributes);
846     out_uint8(out, 2 * strlen(pdirent->d_name) + 2); //unicode length
847     out_uint8s(out, 7); //pad?
848     out_uint8(out, 0); //8.3 file length
849     out_uint8s(out, 2 * 12); //8.3 unicode length
850     rdp_out_unistr(out, pdirent->d_name, 2 * strlen(pdirent->d_name));
851     break;
852    
853     default:
854    
855     unimpl("IRP Query Directory sub: 0x%x\n", info_class);
856     return STATUS_INVALID_PARAMETER;
857     }
858    
859     return STATUS_SUCCESS;
860     }
861    
862 n-ki 600
863    
864     static NTSTATUS
865     disk_device_control(HANDLE handle, uint32 request, STREAM in, STREAM out)
866     {
867     uint32 result;
868    
869     if (((request >> 16) != 20) || ((request >> 16) != 9))
870     return STATUS_INVALID_PARAMETER;
871    
872     /* extract operation */
873     request >>= 2;
874     request &= 0xfff;
875    
876     printf("DISK IOCTL %d\n", request);
877    
878     switch (request)
879     {
880     case 25: // ?
881     case 42: // ?
882     default:
883     unimpl("DISK IOCTL %d\n", request);
884     return STATUS_INVALID_PARAMETER;
885     }
886    
887     return STATUS_SUCCESS;
888     }
889    
890 n-ki 569 DEVICE_FNS disk_fns = {
891     disk_create,
892     disk_close,
893     disk_read,
894     disk_write,
895 n-ki 600 disk_device_control /* device_control */
896 n-ki 569 };

  ViewVC Help
Powered by ViewVC 1.1.26