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

Annotation of /jpeg/rdesktop/trunk/disk.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 661 - (hide annotations)
Fri Apr 16 13:03:13 2004 UTC (20 years, 1 month ago) by astrand
Original Path: sourceforge.net/trunk/rdesktop/disk.c
File MIME type: text/plain
File size: 21832 byte(s)
FileEndOfFileInformation actually calls ftrunc().
FileAllocationInformation falls through to FileEndOfFileInformation.

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 n-ki 615 #include <sys/mntent.h>
48 stargo 618 /* TODO: Fix mntent-handling for solaris */
49     #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 n-ki 600 time_t
88     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     void
103     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     time_t
114     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 n-ki 569 NTSTATUS
166     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     NTSTATUS
323     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     NTSTATUS
343     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     NTSTATUS
380     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 661 if (ftruncate(handle, length) != 0)
657     {
658     perror("ftruncate");
659     return STATUS_DISK_FULL;
660     }
661    
662 n-ki 569 break;
663     default:
664    
665     unimpl("IRP Set File Information class: 0x%x\n", info_class);
666     return STATUS_INVALID_PARAMETER;
667     }
668     return STATUS_SUCCESS;
669     }
670    
671 n-ki 615 FsInfoType *
672     FsVolumeInfo(char *fpath)
673     {
674    
675     #ifdef HAVE_MNTENT_H
676     FILE *fdfs;
677     struct mntent *e;
678     static FsInfoType info;
679    
680     /* initialize */
681     memset(&info, 0, sizeof(info));
682     strcpy(info.label, "RDESKTOP");
683     strcpy(info.type, "RDPFS");
684    
685     fdfs = setmntent(MNTENT_PATH, "r");
686     if (!fdfs)
687     return &info;
688    
689     while ((e = getmntent(fdfs)))
690     {
691     if (strncmp(fpath, e->mnt_dir, strlen(fpath)) == 0)
692     {
693     strcpy(info.type, e->mnt_type);
694     strcpy(info.name, e->mnt_fsname);
695     if (strstr(e->mnt_opts, "vfat") || strstr(e->mnt_opts, "iso9660"))
696     {
697     int fd = open(e->mnt_fsname, O_RDONLY);
698     if (fd >= 0)
699     {
700     unsigned char buf[512];
701     memset(buf, 0, sizeof(buf));
702     if (strstr(e->mnt_opts, "vfat"))
703     /*FAT*/
704     {
705     strcpy(info.type, "vfat");
706     read(fd, buf, sizeof(buf));
707     info.serial =
708     (buf[42] << 24) + (buf[41] << 16) +
709     (buf[40] << 8) + buf[39];
710     strncpy(info.label, buf + 43, 10);
711     info.label[10] = '\0';
712     }
713     else if (lseek(fd, 32767, SEEK_SET) >= 0) /* ISO9660 */
714     {
715     read(fd, buf, sizeof(buf));
716     strncpy(info.label, buf + 41, 32);
717     info.label[32] = '\0';
718     //info.Serial = (buf[128]<<24)+(buf[127]<<16)+(buf[126]<<8)+buf[125];
719     }
720     close(fd);
721     }
722     }
723     }
724     }
725     endmntent(fdfs);
726     #else
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     #endif
735     return &info;
736     }
737    
738    
739 n-ki 569 NTSTATUS
740     disk_query_volume_information(HANDLE handle, uint32 info_class, STREAM out)
741     {
742 stargo 574 struct STATFS_T stat_fs;
743 n-ki 569 struct fileinfo *pfinfo;
744 n-ki 615 FsInfoType *fsinfo;
745 n-ki 569
746     pfinfo = &(g_fileinfo[handle]);
747    
748 n-ki 600 if (STATFS_FN(pfinfo->path, &stat_fs) != 0)
749 n-ki 569 {
750     perror("statfs");
751     return STATUS_ACCESS_DENIED;
752     }
753    
754 n-ki 615 fsinfo = FsVolumeInfo(pfinfo->path);
755    
756 n-ki 569 switch (info_class)
757     {
758 astrand 653 case FileFsVolumeInformation:
759 n-ki 569
760     out_uint32_le(out, 0); /* volume creation time low */
761     out_uint32_le(out, 0); /* volume creation time high */
762 n-ki 615 out_uint32_le(out, fsinfo->serial); /* serial */
763    
764     out_uint32_le(out, 2 * strlen(fsinfo->label)); /* length of string */
765    
766 n-ki 569 out_uint8(out, 0); /* support objects? */
767 n-ki 615 rdp_out_unistr(out, fsinfo->label, 2 * strlen(fsinfo->label) - 2);
768 n-ki 569 break;
769    
770 astrand 653 case FileFsSizeInformation:
771 n-ki 569
772     out_uint32_le(out, stat_fs.f_blocks); /* Total allocation units low */
773     out_uint32_le(out, 0); /* Total allocation high units */
774     out_uint32_le(out, stat_fs.f_bfree); /* Available allocation units */
775     out_uint32_le(out, 0); /* Available allowcation units */
776     out_uint32_le(out, stat_fs.f_bsize / 0x200); /* Sectors per allocation unit */
777     out_uint32_le(out, 0x200); /* Bytes per sector */
778     break;
779    
780 astrand 653 case FileFsAttributeInformation:
781 n-ki 569
782     out_uint32_le(out, FS_CASE_SENSITIVE | FS_CASE_IS_PRESERVED); /* fs attributes */
783 stargo 574 out_uint32_le(out, F_NAMELEN(stat_fs)); /* max length of filename */
784 n-ki 615
785     out_uint32_le(out, 2 * strlen(fsinfo->type)); /* length of fs_type */
786     rdp_out_unistr(out, fsinfo->type, 2 * strlen(fsinfo->type) - 2);
787 n-ki 569 break;
788    
789 astrand 653 case FileFsLabelInformation:
790     case FileFsDeviceInformation:
791     case FileFsControlInformation:
792     case FileFsFullSizeInformation:
793     case FileFsObjectIdInformation:
794     case FileFsMaximumInformation:
795    
796 n-ki 569 default:
797    
798     unimpl("IRP Query Volume Information class: 0x%x\n", info_class);
799     return STATUS_INVALID_PARAMETER;
800     }
801     return STATUS_SUCCESS;
802     }
803    
804     NTSTATUS
805     disk_query_directory(HANDLE handle, uint32 info_class, char *pattern, STREAM out)
806     {
807     uint32 file_attributes, ft_low, ft_high;
808     char *dirname, fullpath[256];
809     DIR *pdir;
810     struct dirent *pdirent;
811     struct stat fstat;
812     struct fileinfo *pfinfo;
813    
814     pfinfo = &(g_fileinfo[handle]);
815     pdir = pfinfo->pdir;
816     dirname = pfinfo->path;
817     file_attributes = 0;
818    
819     switch (info_class)
820     {
821     case 3: //FIXME: Why 3?
822    
823     // If a search pattern is received, remember this pattern, and restart search
824     if (pattern[0] != 0)
825     {
826     strncpy(pfinfo->pattern, 1 + strrchr(pattern, '/'), 64);
827     rewinddir(pdir);
828     }
829    
830     // find next dirent matching pattern
831     pdirent = readdir(pdir);
832     while (pdirent && fnmatch(pfinfo->pattern, pdirent->d_name, 0) != 0)
833     pdirent = readdir(pdir);
834    
835     if (pdirent == NULL)
836     return STATUS_NO_MORE_FILES;
837    
838     // Get information for directory entry
839     sprintf(fullpath, "%s/%s", dirname, pdirent->d_name);
840 n-ki 600
841 n-ki 596 /* JIF
842 n-ki 569 printf("Stat: %s\n", fullpath); */
843     if (stat(fullpath, &fstat))
844     {
845     perror("stat");
846     out_uint8(out, 0);
847     return STATUS_ACCESS_DENIED;
848     }
849    
850     if (S_ISDIR(fstat.st_mode))
851     file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
852     if (pdirent->d_name[0] == '.')
853     file_attributes |= FILE_ATTRIBUTE_HIDDEN;
854 n-ki 600 if (!file_attributes)
855     file_attributes |= FILE_ATTRIBUTE_NORMAL;
856     if (!(fstat.st_mode & S_IWUSR))
857     file_attributes |= FILE_ATTRIBUTE_READONLY;
858 n-ki 569
859     // Return requested information
860     out_uint8s(out, 8); //unknown zero
861    
862 n-ki 600 seconds_since_1970_to_filetime(get_create_time(&fstat), &ft_high, &ft_low);
863     out_uint32_le(out, ft_low); // create time
864     out_uint32_le(out, ft_high);
865    
866 n-ki 569 seconds_since_1970_to_filetime(fstat.st_atime, &ft_high, &ft_low);
867     out_uint32_le(out, ft_low); //last_access_time
868     out_uint32_le(out, ft_high);
869    
870     seconds_since_1970_to_filetime(fstat.st_mtime, &ft_high, &ft_low);
871     out_uint32_le(out, ft_low); //last_write_time
872     out_uint32_le(out, ft_high);
873    
874 n-ki 600 seconds_since_1970_to_filetime(fstat.st_ctime, &ft_high, &ft_low);
875     out_uint32_le(out, ft_low); //change_write_time
876     out_uint32_le(out, ft_high);
877    
878 n-ki 569 out_uint32_le(out, fstat.st_size); //filesize low
879     out_uint32_le(out, 0); //filesize high
880     out_uint32_le(out, fstat.st_size); //filesize low
881     out_uint32_le(out, 0); //filesize high
882     out_uint32_le(out, file_attributes);
883     out_uint8(out, 2 * strlen(pdirent->d_name) + 2); //unicode length
884     out_uint8s(out, 7); //pad?
885     out_uint8(out, 0); //8.3 file length
886     out_uint8s(out, 2 * 12); //8.3 unicode length
887     rdp_out_unistr(out, pdirent->d_name, 2 * strlen(pdirent->d_name));
888     break;
889    
890     default:
891    
892     unimpl("IRP Query Directory sub: 0x%x\n", info_class);
893     return STATUS_INVALID_PARAMETER;
894     }
895    
896     return STATUS_SUCCESS;
897     }
898    
899 n-ki 600
900    
901     static NTSTATUS
902     disk_device_control(HANDLE handle, uint32 request, STREAM in, STREAM out)
903     {
904     uint32 result;
905    
906     if (((request >> 16) != 20) || ((request >> 16) != 9))
907     return STATUS_INVALID_PARAMETER;
908    
909     /* extract operation */
910     request >>= 2;
911     request &= 0xfff;
912    
913     printf("DISK IOCTL %d\n", request);
914    
915     switch (request)
916     {
917     case 25: // ?
918     case 42: // ?
919     default:
920     unimpl("DISK IOCTL %d\n", request);
921     return STATUS_INVALID_PARAMETER;
922     }
923    
924     return STATUS_SUCCESS;
925     }
926    
927 n-ki 569 DEVICE_FNS disk_fns = {
928     disk_create,
929     disk_close,
930     disk_read,
931     disk_write,
932 n-ki 600 disk_device_control /* device_control */
933 n-ki 569 };

  ViewVC Help
Powered by ViewVC 1.1.26