/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/disk.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 627 - (show annotations)
Thu Mar 4 08:24:40 2004 UTC (20 years, 3 months ago) by n-ki
Original Path: sourceforge.net/trunk/rdesktop/disk.c
File MIME type: text/plain
File size: 23616 byte(s)
move disk info define to types.h
extract aio remove
handle errors in aio read / write
function that checks if handle is ok - seems windows cant keep track of them huh
- volker milde

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

  ViewVC Help
Powered by ViewVC 1.1.26