/[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 601 - (hide annotations)
Fri Feb 6 12:57:26 2004 UTC (20 years, 3 months ago) by n-ki
File MIME type: text/plain
File size: 21599 byte(s)
support for deleting directories.

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

  ViewVC Help
Powered by ViewVC 1.1.26