/[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 786 - (hide annotations)
Thu Oct 21 08:13:33 2004 UTC (19 years, 7 months ago) by astrand
File MIME type: text/plain
File size: 23486 byte(s)
Removed unused variables.

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

  ViewVC Help
Powered by ViewVC 1.1.26