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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 612 - (show annotations)
Mon Feb 23 09:58:16 2004 UTC (20 years, 2 months ago) by n-ki
File MIME type: text/plain
File size: 21989 byte(s)
better error handling in rdpdr and disk.c - partial merge of Volker Mildes patch.

1 /* -*- 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 #define FILE_ATTRIBUTE_UNKNOWNXXX0 0x00000060 /* ??? ACTION i.e. 0x860 == compress this file ? */
28 #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 #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 #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 #if (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
84 #define SOLARIS
85 #endif
86
87 #if (defined(SOLARIS) || defined(__hpux))
88 #define DIRFD(a) ((a)->dd_fd)
89 #else
90 #define DIRFD(a) (dirfd(a))
91 #endif
92
93 #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
101 #include <utime.h>
102 #include <time.h> /* ctime */
103
104
105 #if (defined(SOLARIS) || defined (__hpux) || defined(__BEOS__))
106 #include <sys/statvfs.h> /* solaris statvfs */
107 #define STATFS_FN(path, buf) (statvfs(path,buf))
108 #define STATFS_T statvfs
109 #define F_NAMELEN(buf) ((buf).f_namemax)
110
111 #elif (defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__))
112 #include <sys/param.h>
113 #include <sys/mount.h>
114 #define STATFS_FN(path, buf) (statfs(path,buf))
115 #define STATFS_T statfs
116 #define F_NAMELEN(buf) (NAME_MAX)
117
118 #else
119 #include <sys/vfs.h> /* linux statfs */
120 #define STATFS_FN(path, buf) (statfs(path,buf))
121 #define STATFS_T statfs
122 #define F_NAMELEN(buf) ((buf).f_namelen)
123 #endif
124
125 #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 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 /* 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 /* 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 /* Enumeration of devices from rdesktop.c */
183 /* returns numer of units found and initialized. */
184 /* optarg looks like ':h=/mnt/floppy,b=/mnt/usbdevice1' */
185 /* when it arrives to this function. */
186 int
187 disk_enum_devices(uint32 * id, char *optarg)
188 {
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 toupper_str(g_rdpdr_device[*id].name);
201
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 /* Opens or creates a file or directory */
218 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 struct stat filestat;
227
228 handle = 0;
229 dirp = NULL;
230 flags = 0;
231 mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
232
233
234 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 //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 {
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
282 if (flags_and_attributes & FILE_DIRECTORY_FILE)
283 {
284 if (flags & O_CREAT)
285 {
286 mkdir(path, mode);
287 }
288
289 dirp = opendir(path);
290 if (!dirp)
291 {
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 perror("opendir");
305 return STATUS_NO_SUCH_FILE;
306 }
307 }
308 handle = DIRFD(dirp);
309 }
310 else
311 {
312
313 if (accessmask & GENERIC_ALL
314 || (accessmask & GENERIC_READ && accessmask & GENERIC_WRITE))
315 {
316 flags |= O_RDWR;
317 }
318 else if ((accessmask & GENERIC_WRITE) && !(accessmask & GENERIC_READ))
319 {
320 flags |= O_WRONLY;
321 }
322 else
323 {
324 flags |= O_RDONLY;
325 }
326
327 handle = open(path, flags, mode);
328 if (handle == -1)
329 {
330 switch (errno)
331 {
332 case EISDIR:
333
334 return STATUS_FILE_IS_A_DIRECTORY;
335
336 case EACCES:
337
338 return STATUS_ACCESS_DENIED;
339
340 case ENOENT:
341
342 return STATUS_NO_SUCH_FILE;
343 case EEXIST:
344
345 return STATUS_OBJECT_NAME_COLLISION;
346 default:
347
348 perror("open");
349 return STATUS_NO_SUCH_FILE;
350 }
351 }
352
353 /* all read and writes of files should be non blocking */
354 if (fcntl(handle, F_SETFL, O_NONBLOCK) == -1)
355 perror("fcntl");
356 }
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 #if 0
401 /* 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 #endif
409
410 if (offset)
411 lseek(handle, offset, SEEK_SET);
412 n = read(handle, data, length);
413
414 if (n < 0)
415 {
416 *result = 0;
417 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 }
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 if (offset)
438 lseek(handle, offset, SEEK_SET);
439
440 n = write(handle, data, length);
441
442 if (n < 0)
443 {
444 perror("write");
445 *result = 0;
446 switch (errno)
447 {
448 case ENOSPC:
449 return STATUS_DISK_FULL;
450 default:
451 return STATUS_ACCESS_DENIED;
452 }
453 }
454
455 *result = n;
456
457 return STATUS_SUCCESS;
458 }
459
460 NTSTATUS
461 disk_query_information(HANDLE handle, uint32 info_class, STREAM out)
462 {
463 uint32 file_attributes, ft_high, ft_low;
464 struct stat filestat;
465 char *path, *filename;
466
467 path = g_fileinfo[handle].path;
468
469 // Get information about file
470 if (fstat(handle, &filestat) != 0)
471 {
472 perror("stat");
473 out_uint8(out, 0);
474 return STATUS_ACCESS_DENIED;
475 }
476
477 // Set file attributes
478 file_attributes = 0;
479 if (S_ISDIR(filestat.st_mode))
480 file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
481
482 filename = 1 + strrchr(path, '/');
483 if (filename && filename[0] == '.')
484 file_attributes |= FILE_ATTRIBUTE_HIDDEN;
485
486 if (!file_attributes)
487 file_attributes |= FILE_ATTRIBUTE_NORMAL;
488
489 if (!(filestat.st_mode & S_IWUSR))
490 file_attributes |= FILE_ATTRIBUTE_READONLY;
491
492 // Return requested data
493 switch (info_class)
494 {
495 case 4: /* FileBasicInformation */
496 seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high,
497 &ft_low);
498 out_uint32_le(out, ft_low); //create_access_time
499 out_uint32_le(out, ft_high);
500
501 seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low);
502 out_uint32_le(out, ft_low); //last_access_time
503 out_uint32_le(out, ft_high);
504
505 seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low);
506 out_uint32_le(out, ft_low); //last_write_time
507 out_uint32_le(out, ft_high);
508
509 seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low);
510 out_uint32_le(out, ft_low); //last_change_time
511 out_uint32_le(out, ft_high);
512
513 out_uint32_le(out, file_attributes);
514 break;
515
516 case 5: /* FileStandardInformation */
517
518 out_uint32_le(out, filestat.st_size); //Allocation size
519 out_uint32_le(out, 0);
520 out_uint32_le(out, filestat.st_size); //End of file
521 out_uint32_le(out, 0);
522 out_uint32_le(out, filestat.st_nlink); //Number of links
523 out_uint8(out, 0); //Delete pending
524 out_uint8(out, S_ISDIR(filestat.st_mode) ? 1 : 0); //Directory
525 break;
526
527 case 35: /* FileObjectIdInformation */
528
529 out_uint32_le(out, file_attributes); /* File Attributes */
530 out_uint32_le(out, 0); /* Reparse Tag */
531 break;
532
533 default:
534
535 unimpl("IRP Query (File) Information class: 0x%x\n", info_class);
536 return STATUS_INVALID_PARAMETER;
537 }
538 return STATUS_SUCCESS;
539 }
540
541 NTSTATUS
542 disk_set_information(HANDLE handle, uint32 info_class, STREAM in, STREAM out)
543 {
544 uint32 device_id, length, file_attributes, ft_high, ft_low;
545 char newname[256], fullpath[256];
546 struct fileinfo *pfinfo;
547
548 int mode;
549 struct stat filestat;
550 time_t write_time, change_time, access_time, mod_time;
551 struct utimbuf tvs;
552 struct STATFS_T stat_fs;
553
554 pfinfo = &(g_fileinfo[handle]);
555
556 switch (info_class)
557 {
558 case 4: /* FileBasicInformation */
559 write_time = change_time = access_time = 0;
560
561 in_uint8s(in, 4); /* Handle of root dir? */
562 in_uint8s(in, 24); /* unknown */
563
564 // CreationTime
565 in_uint32_le(in, ft_low);
566 in_uint32_le(in, ft_high);
567
568 // AccessTime
569 in_uint32_le(in, ft_low);
570 in_uint32_le(in, ft_high);
571 if (ft_low || ft_high)
572 access_time = convert_1970_to_filetime(ft_high, ft_low);
573
574 // WriteTime
575 in_uint32_le(in, ft_low);
576 in_uint32_le(in, ft_high);
577 if (ft_low || ft_high)
578 write_time = convert_1970_to_filetime(ft_high, ft_low);
579
580 // ChangeTime
581 in_uint32_le(in, ft_low);
582 in_uint32_le(in, ft_high);
583 if (ft_low || ft_high)
584 change_time = convert_1970_to_filetime(ft_high, ft_low);
585
586 in_uint32_le(in, file_attributes);
587
588 if (fstat(handle, &filestat))
589 return STATUS_ACCESS_DENIED;
590
591 tvs.modtime = filestat.st_mtime;
592 tvs.actime = filestat.st_atime;
593 if (access_time)
594 tvs.actime = access_time;
595
596
597 if (write_time || change_time)
598 mod_time = MIN(write_time, change_time);
599 else
600 mod_time = write_time ? write_time : change_time;
601
602 if (mod_time)
603 tvs.modtime = mod_time;
604
605
606 if (access_time || write_time || change_time)
607 {
608 #if WITH_DEBUG_RDP5
609 printf("FileBasicInformation access time %s",
610 ctime(&tvs.actime));
611 printf("FileBasicInformation modification time %s",
612 ctime(&tvs.modtime));
613 #endif
614 if (utime(pfinfo->path, &tvs))
615 return STATUS_ACCESS_DENIED;
616 }
617
618 if (!file_attributes)
619 break; // not valid
620
621 mode = filestat.st_mode;
622
623 if (file_attributes & FILE_ATTRIBUTE_READONLY)
624 mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
625 else
626 mode |= S_IWUSR;
627
628 mode &= 0777;
629 #if WITH_DEBUG_RDP5
630 printf("FileBasicInformation set access mode 0%o", mode);
631 #endif
632
633 if (fchmod(handle, mode))
634 return STATUS_ACCESS_DENIED;
635
636 /* prevents start of writing if not enough space left on device */
637 if (STATFS_FN(g_rdpdr_device[pfinfo->device_id].local_path, &stat_fs) == 0)
638 if (stat_fs.f_bsize * stat_fs.f_bfree < length)
639 return STATUS_DISK_FULL;
640
641 break;
642
643 case 10: /* FileRenameInformation */
644
645 in_uint8s(in, 4); /* Handle of root dir? */
646 in_uint8s(in, 0x1a); /* unknown */
647 in_uint32_le(in, length);
648
649 if (length && (length / 2) < 256)
650 {
651 rdp_in_unistr(in, newname, length);
652 convert_to_unix_filename(newname);
653 }
654 else
655 {
656 return STATUS_INVALID_PARAMETER;
657 }
658
659 sprintf(fullpath, "%s%s", g_rdpdr_device[pfinfo->device_id].local_path,
660 newname);
661
662 if (rename(pfinfo->path, fullpath) != 0)
663 {
664 perror("rename");
665 return STATUS_ACCESS_DENIED;
666 }
667 break;
668
669 case 13: /* FileDispositionInformation */
670
671 //unimpl("IRP Set File Information class: FileDispositionInformation\n");
672
673 //in_uint32_le(in, delete_on_close);
674 // disk_close(handle);
675 if ((pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE)) // remove a directory
676 {
677 if (rmdir(pfinfo->path) < 0)
678 return STATUS_ACCESS_DENIED;
679 }
680 else if (unlink(pfinfo->path) < 0) // unlink a file
681 return STATUS_ACCESS_DENIED;
682
683 break;
684
685 case 19: /* FileAllocationInformation */
686
687 unimpl("IRP Set File Information class: FileAllocationInformation\n");
688 break;
689
690 case 20: /* FileEndOfFileInformation */
691 in_uint8s(in, 28); /* unknown */
692 in_uint32_le(in, length); /* file size */
693
694 printf("FileEndOfFileInformation length = %d\n", length);
695 // ????????????
696
697 unimpl("IRP Set File Information class: FileEndOfFileInformation\n");
698 break;
699 default:
700
701 unimpl("IRP Set File Information class: 0x%x\n", info_class);
702 return STATUS_INVALID_PARAMETER;
703 }
704 return STATUS_SUCCESS;
705 }
706
707 NTSTATUS
708 disk_query_volume_information(HANDLE handle, uint32 info_class, STREAM out)
709 {
710 char *volume, *fs_type;
711 struct STATFS_T stat_fs;
712 struct fileinfo *pfinfo;
713
714 pfinfo = &(g_fileinfo[handle]);
715 volume = "RDESKTOP";
716 fs_type = "RDPFS";
717
718 if (STATFS_FN(pfinfo->path, &stat_fs) != 0)
719 {
720 perror("statfs");
721 return STATUS_ACCESS_DENIED;
722 }
723
724 switch (info_class)
725 {
726 case 1: /* FileFsVolumeInformation */
727
728 out_uint32_le(out, 0); /* volume creation time low */
729 out_uint32_le(out, 0); /* volume creation time high */
730 out_uint32_le(out, 0); /* serial */
731 out_uint32_le(out, 2 * strlen(volume)); /* length of string */
732 out_uint8(out, 0); /* support objects? */
733 rdp_out_unistr(out, volume, 2 * strlen(volume) - 2);
734 break;
735
736 case 3: /* FileFsSizeInformation */
737
738 out_uint32_le(out, stat_fs.f_blocks); /* Total allocation units low */
739 out_uint32_le(out, 0); /* Total allocation high units */
740 out_uint32_le(out, stat_fs.f_bfree); /* Available allocation units */
741 out_uint32_le(out, 0); /* Available allowcation units */
742 out_uint32_le(out, stat_fs.f_bsize / 0x200); /* Sectors per allocation unit */
743 out_uint32_le(out, 0x200); /* Bytes per sector */
744 break;
745
746 case 5: /* FileFsAttributeInformation */
747
748 out_uint32_le(out, FS_CASE_SENSITIVE | FS_CASE_IS_PRESERVED); /* fs attributes */
749 out_uint32_le(out, F_NAMELEN(stat_fs)); /* max length of filename */
750 out_uint32_le(out, 2 * strlen(fs_type)); /* length of fs_type */
751 rdp_out_unistr(out, fs_type, 2 * strlen(fs_type) - 2);
752 break;
753
754 case 2: /* FileFsLabelInformation */
755 case 4: /* FileFsDeviceInformation */
756 case 6: /* FileFsControlInformation */
757 case 7: /* FileFsFullSizeInformation */
758 case 8: /* FileFsObjectIdInformation */
759 case 9: /* FileFsMaximumInformation */
760 default:
761
762 unimpl("IRP Query Volume Information class: 0x%x\n", info_class);
763 return STATUS_INVALID_PARAMETER;
764 }
765 return STATUS_SUCCESS;
766 }
767
768 NTSTATUS
769 disk_query_directory(HANDLE handle, uint32 info_class, char *pattern, STREAM out)
770 {
771 uint32 file_attributes, ft_low, ft_high;
772 char *dirname, fullpath[256];
773 DIR *pdir;
774 struct dirent *pdirent;
775 struct stat fstat;
776 struct fileinfo *pfinfo;
777
778 pfinfo = &(g_fileinfo[handle]);
779 pdir = pfinfo->pdir;
780 dirname = pfinfo->path;
781 file_attributes = 0;
782
783 switch (info_class)
784 {
785 case 3: //FIXME: Why 3?
786
787 // If a search pattern is received, remember this pattern, and restart search
788 if (pattern[0] != 0)
789 {
790 strncpy(pfinfo->pattern, 1 + strrchr(pattern, '/'), 64);
791 rewinddir(pdir);
792 }
793
794 // find next dirent matching pattern
795 pdirent = readdir(pdir);
796 while (pdirent && fnmatch(pfinfo->pattern, pdirent->d_name, 0) != 0)
797 pdirent = readdir(pdir);
798
799 if (pdirent == NULL)
800 return STATUS_NO_MORE_FILES;
801
802 // Get information for directory entry
803 sprintf(fullpath, "%s/%s", dirname, pdirent->d_name);
804
805 /* JIF
806 printf("Stat: %s\n", fullpath); */
807 if (stat(fullpath, &fstat))
808 {
809 perror("stat");
810 out_uint8(out, 0);
811 return STATUS_ACCESS_DENIED;
812 }
813
814 if (S_ISDIR(fstat.st_mode))
815 file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
816 if (pdirent->d_name[0] == '.')
817 file_attributes |= FILE_ATTRIBUTE_HIDDEN;
818 if (!file_attributes)
819 file_attributes |= FILE_ATTRIBUTE_NORMAL;
820 if (!(fstat.st_mode & S_IWUSR))
821 file_attributes |= FILE_ATTRIBUTE_READONLY;
822
823 // Return requested information
824 out_uint8s(out, 8); //unknown zero
825
826 seconds_since_1970_to_filetime(get_create_time(&fstat), &ft_high, &ft_low);
827 out_uint32_le(out, ft_low); // create time
828 out_uint32_le(out, ft_high);
829
830 seconds_since_1970_to_filetime(fstat.st_atime, &ft_high, &ft_low);
831 out_uint32_le(out, ft_low); //last_access_time
832 out_uint32_le(out, ft_high);
833
834 seconds_since_1970_to_filetime(fstat.st_mtime, &ft_high, &ft_low);
835 out_uint32_le(out, ft_low); //last_write_time
836 out_uint32_le(out, ft_high);
837
838 seconds_since_1970_to_filetime(fstat.st_ctime, &ft_high, &ft_low);
839 out_uint32_le(out, ft_low); //change_write_time
840 out_uint32_le(out, ft_high);
841
842 out_uint32_le(out, fstat.st_size); //filesize low
843 out_uint32_le(out, 0); //filesize high
844 out_uint32_le(out, fstat.st_size); //filesize low
845 out_uint32_le(out, 0); //filesize high
846 out_uint32_le(out, file_attributes);
847 out_uint8(out, 2 * strlen(pdirent->d_name) + 2); //unicode length
848 out_uint8s(out, 7); //pad?
849 out_uint8(out, 0); //8.3 file length
850 out_uint8s(out, 2 * 12); //8.3 unicode length
851 rdp_out_unistr(out, pdirent->d_name, 2 * strlen(pdirent->d_name));
852 break;
853
854 default:
855
856 unimpl("IRP Query Directory sub: 0x%x\n", info_class);
857 return STATUS_INVALID_PARAMETER;
858 }
859
860 return STATUS_SUCCESS;
861 }
862
863
864
865 static NTSTATUS
866 disk_device_control(HANDLE handle, uint32 request, STREAM in, STREAM out)
867 {
868 uint32 result;
869
870 if (((request >> 16) != 20) || ((request >> 16) != 9))
871 return STATUS_INVALID_PARAMETER;
872
873 /* extract operation */
874 request >>= 2;
875 request &= 0xfff;
876
877 printf("DISK IOCTL %d\n", request);
878
879 switch (request)
880 {
881 case 25: // ?
882 case 42: // ?
883 default:
884 unimpl("DISK IOCTL %d\n", request);
885 return STATUS_INVALID_PARAMETER;
886 }
887
888 return STATUS_SUCCESS;
889 }
890
891 DEVICE_FNS disk_fns = {
892 disk_create,
893 disk_close,
894 disk_read,
895 disk_write,
896 disk_device_control /* device_control */
897 };

  ViewVC Help
Powered by ViewVC 1.1.26