/[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 616 - (show annotations)
Tue Feb 24 15:24:38 2004 UTC (20 years, 3 months ago) by n-ki
File MIME type: text/plain
File size: 23721 byte(s)
a bad diff by me in disk.c 1.13 - 1.14 this is where the code should be, thanks for the correction volker

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

  ViewVC Help
Powered by ViewVC 1.1.26