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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 696 - (hide annotations)
Tue May 11 12:46:39 2004 UTC (20 years ago) by astrand
File MIME type: text/plain
File size: 22106 byte(s)
Using constant FileBothDirectoryInformation instead of
hardcoded value 3. Added FIXME for other return types.

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

  ViewVC Help
Powered by ViewVC 1.1.26