/[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 602 - (show annotations)
Sat Feb 7 17:32:21 2004 UTC (20 years, 2 months ago) by stargo
File MIME type: text/plain
File size: 21602 byte(s)
Cleanup some warnings (from SUNWspro-compiler)

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 #ifdef SOLARIS
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)
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
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 /* 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 /* 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 /* 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(uint32 *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 toupper_str(g_rdpdr_device[*id].name);
202
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 /* Opens or creates a file or directory */
219 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 struct stat filestat;
228
229 handle = 0;
230 dirp = NULL;
231 flags = 0;
232 mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
233
234
235 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 //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 {
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
283 if (flags_and_attributes & FILE_DIRECTORY_FILE)
284 {
285 if (flags & O_CREAT)
286 {
287 mkdir(path, mode);
288 }
289
290 dirp = opendir(path);
291 if (!dirp)
292 {
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 perror("opendir");
306 return STATUS_NO_SUCH_FILE;
307 }
308 }
309 handle = DIRFD(dirp);
310 }
311 else
312 {
313
314 if (accessmask & GENERIC_ALL
315 || (accessmask & GENERIC_READ && accessmask & GENERIC_WRITE))
316 {
317 flags |= O_RDWR;
318 }
319 else if ((accessmask & GENERIC_WRITE) && !(accessmask & GENERIC_READ))
320 {
321 flags |= O_WRONLY;
322 }
323 else
324 {
325 flags |= O_RDONLY;
326 }
327
328 handle = open(path, flags, mode);
329 if (handle == -1)
330 {
331 switch (errno)
332 {
333 case EISDIR:
334
335 return STATUS_FILE_IS_A_DIRECTORY;
336
337 case EACCES:
338
339 return STATUS_ACCESS_DENIED;
340
341 case ENOENT:
342
343 return STATUS_NO_SUCH_FILE;
344 default:
345
346 perror("open");
347 return STATUS_NO_SUCH_FILE;
348 }
349 }
350
351 /* all read and writes of files should be non blocking */
352 if (fcntl(handle, F_SETFL, O_NONBLOCK) == -1)
353 perror("fcntl");
354 }
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 #if 0
399 /* 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 #endif
407
408 if (offset)
409 lseek(handle, offset, SEEK_SET);
410 n = read(handle, data, length);
411
412 if (n < 0)
413 {
414 *result = 0;
415 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 }
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 switch (errno)
445 {
446 case ENOSPC:
447 return STATUS_DISK_FULL;
448 default:
449 return STATUS_ACCESS_DENIED;
450 }
451 }
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
480 filename = 1 + strrchr(path, '/');
481 if (filename && filename[0] == '.')
482 file_attributes |= FILE_ATTRIBUTE_HIDDEN;
483
484 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 // Return requested data
491 switch (info_class)
492 {
493 case 4: /* FileBasicInformation */
494 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
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 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 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 int mode;
547 struct stat filestat;
548 time_t write_time, change_time, access_time, mod_time;
549 struct utimbuf tvs;
550
551 pfinfo = &(g_fileinfo[handle]);
552
553 switch (info_class)
554 {
555 case 4: /* FileBasicInformation */
556 write_time = change_time = access_time = 0;
557
558 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 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
664 //in_uint32_le(in, delete_on_close);
665 // disk_close(handle);
666 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 break;
675
676 case 19: /* FileAllocationInformation */
677
678 unimpl("IRP Set File Information class: FileAllocationInformation\n");
679 break;
680
681 case 20: /* FileEndOfFileInformation */
682 in_uint8s(in, 28); /* unknown */
683 in_uint32_le(in, length); /* file size */
684
685 printf("FileEndOfFileInformation length = %d\n", length);
686 // ????????????
687
688 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 struct STATFS_T stat_fs;
703 struct fileinfo *pfinfo;
704
705 pfinfo = &(g_fileinfo[handle]);
706 volume = "RDESKTOP";
707 fs_type = "RDPFS";
708
709 if (STATFS_FN(pfinfo->path, &stat_fs) != 0)
710 {
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 out_uint32_le(out, F_NAMELEN(stat_fs)); /* max length of filename */
741 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
796 /* JIF
797 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 if (!file_attributes)
810 file_attributes |= FILE_ATTRIBUTE_NORMAL;
811 if (!(fstat.st_mode & S_IWUSR))
812 file_attributes |= FILE_ATTRIBUTE_READONLY;
813
814 // Return requested information
815 out_uint8s(out, 8); //unknown zero
816
817 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 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 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 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
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 DEVICE_FNS disk_fns = {
883 disk_create,
884 disk_close,
885 disk_read,
886 disk_write,
887 disk_device_control /* device_control */
888 };

  ViewVC Help
Powered by ViewVC 1.1.26