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

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

  ViewVC Help
Powered by ViewVC 1.1.26