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

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

  ViewVC Help
Powered by ViewVC 1.1.26