/[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 618 - (show annotations)
Sat Feb 28 10:52:29 2004 UTC (20 years, 3 months ago) by stargo
File MIME type: text/plain
File size: 23764 byte(s)
mntent on solaris is different than on linux.
Need to port it when I have more time...
Disable it on solaris for the time being

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

  ViewVC Help
Powered by ViewVC 1.1.26