/[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 627 - (hide annotations)
Thu Mar 4 08:24:40 2004 UTC (20 years, 2 months ago) by n-ki
File MIME type: text/plain
File size: 23616 byte(s)
move disk info define to types.h
extract aio remove
handle errors in aio read / write
function that checks if handle is ok - seems windows cant keep track of them huh
- volker milde

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

  ViewVC Help
Powered by ViewVC 1.1.26