/[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 1435 - (hide annotations)
Sat Feb 16 00:15:43 2008 UTC (16 years, 4 months ago) by matthewc
File MIME type: text/plain
File size: 28984 byte(s)
Fix from Paul Whitaker:  It is not safe to assume that free space
available at the top of the tree is indicative of free space anywhere in
the tree, because you may wish to redirect a mount point hierarchy.

1 n-ki 569 /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.
3     Disk Redirection
4 jsorg71 1365 Copyright (C) Jeroen Meijer 2003-2007
5 n-ki 569
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 902 #include <stdio.h>
31 stargo 572
32 n-ki 600 #include <utime.h>
33     #include <time.h> /* ctime */
34    
35 stargo 759 #if (defined(HAVE_DIRFD) || (HAVE_DECL_DIRFD == 1))
36 stargo 742 #define DIRFD(a) (dirfd(a))
37     #else
38     #define DIRFD(a) ((a)->DIR_FD_MEMBER_NAME)
39     #endif
40 n-ki 600
41 stargo 873 /* TODO: Fix mntent-handling for solaris
42     * #include <sys/mntent.h> */
43     #if (defined(HAVE_MNTENT_H) && defined(HAVE_SETMNTENT))
44     #include <mntent.h>
45     #define MNTENT_PATH "/etc/mtab"
46     #define USE_SETMNTENT
47 stargo 742 #endif
48    
49 stargo 873 #ifdef HAVE_SYS_VFS_H
50     #include <sys/vfs.h>
51     #endif
52 stargo 573
53 stargo 873 #ifdef HAVE_SYS_STATVFS_H
54     #include <sys/statvfs.h>
55     #endif
56    
57     #ifdef HAVE_SYS_STATFS_H
58     #include <sys/statfs.h>
59     #endif
60    
61     #ifdef HAVE_SYS_PARAM_H
62 stargo 573 #include <sys/param.h>
63 stargo 873 #endif
64    
65     #ifdef HAVE_SYS_MOUNT_H
66 stargo 573 #include <sys/mount.h>
67 stargo 873 #endif
68    
69     #include "rdesktop.h"
70    
71     #ifdef STAT_STATFS3_OSF1
72     #define STATFS_FN(path, buf) (statfs(path,buf,sizeof(buf)))
73 stargo 574 #define STATFS_T statfs
74 stargo 873 #define USE_STATFS
75     #endif
76 stargo 573
77 stargo 873 #ifdef STAT_STATVFS
78 stargo 745 #define STATFS_FN(path, buf) (statvfs(path,buf))
79     #define STATFS_T statvfs
80 stargo 873 #define USE_STATVFS
81     #endif
82 stargo 745
83 stargo 873 #ifdef STAT_STATVFS64
84     #define STATFS_FN(path, buf) (statvfs64(path,buf))
85     #define STATFS_T statvfs64
86     #define USE_STATVFS
87     #endif
88 stargo 807
89 stargo 873 #if (defined(STAT_STATFS2_FS_DATA) || defined(STAT_STATFS2_BSIZE) || defined(STAT_STATFS2_FSIZE))
90 stargo 574 #define STATFS_FN(path, buf) (statfs(path,buf))
91     #define STATFS_T statfs
92 stargo 873 #define USE_STATFS
93     #endif
94    
95     #ifdef STAT_STATFS4
96     #define STATFS_FN(path, buf) (statfs(path,buf,sizeof(buf),0))
97     #define STATFS_T statfs
98     #define USE_STATFS
99     #endif
100    
101     #if ((defined(USE_STATFS) && defined(HAVE_STRUCT_STATFS_F_NAMEMAX)) || (defined(USE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_NAMEMAX)))
102     #define F_NAMELEN(buf) ((buf).f_namemax)
103     #endif
104    
105     #if ((defined(USE_STATFS) && defined(HAVE_STRUCT_STATFS_F_NAMELEN)) || (defined(USE_STATVFS) && defined(HAVE_STRUCT_STATVFS_F_NAMELEN)))
106 stargo 573 #define F_NAMELEN(buf) ((buf).f_namelen)
107 stargo 572 #endif
108    
109 stargo 873 #ifndef F_NAMELEN
110     #define F_NAMELEN(buf) (255)
111     #endif
112    
113     /* Dummy statfs fallback */
114     #ifndef STATFS_T
115     struct dummy_statfs_t
116     {
117 stargo 875 long f_bfree;
118     long f_bsize;
119     long f_blocks;
120     int f_namelen;
121     int f_namemax;
122 stargo 873 };
123 stargo 875
124 astrand 943 static int
125 astrand 879 dummy_statfs(struct dummy_statfs_t *buf)
126 stargo 875 {
127 astrand 879 buf->f_blocks = 262144;
128     buf->f_bfree = 131072;
129     buf->f_bsize = 512;
130     buf->f_namelen = 255;
131     buf->f_namemax = 255;
132 stargo 875
133     return 0;
134     }
135    
136 stargo 873 #define STATFS_T dummy_statfs_t
137 stargo 875 #define STATFS_FN(path,buf) (dummy_statfs(buf))
138 stargo 873 #endif
139    
140 n-ki 569 extern RDPDR_DEVICE g_rdpdr_device[];
141    
142 n-ki 627 FILEINFO g_fileinfo[MAX_OPEN_FILES];
143 jsorg71 1372 RD_BOOL g_notify_stamp = False;
144 n-ki 569
145 n-ki 615 typedef struct
146     {
147 stargo 978 char name[PATH_MAX];
148     char label[PATH_MAX];
149 n-ki 615 unsigned long serial;
150 stargo 978 char type[PATH_MAX];
151 n-ki 615 } FsInfoType;
152    
153 jsorg71 1364 static RD_NTSTATUS NotifyInfo(RD_NTHANDLE handle, uint32 info_class, NOTIFY * p);
154 n-ki 615
155 astrand 664 static time_t
156 astrand 1401 get_create_time(struct stat *filestat)
157 n-ki 600 {
158     time_t ret, ret1;
159    
160 astrand 1401 ret = MIN(filestat->st_ctime, filestat->st_mtime);
161     ret1 = MIN(ret, filestat->st_atime);
162 n-ki 600
163     if (ret1 != (time_t) 0)
164     return ret1;
165    
166     return ret;
167     }
168    
169 n-ki 569 /* Convert seconds since 1970 to a filetime */
170 astrand 664 static void
171 n-ki 569 seconds_since_1970_to_filetime(time_t seconds, uint32 * high, uint32 * low)
172     {
173     unsigned long long ticks;
174    
175     ticks = (seconds + 11644473600LL) * 10000000;
176     *low = (uint32) ticks;
177     *high = (uint32) (ticks >> 32);
178     }
179    
180 n-ki 600 /* Convert seconds since 1970 back to filetime */
181 astrand 664 static time_t
182 n-ki 600 convert_1970_to_filetime(uint32 high, uint32 low)
183     {
184     unsigned long long ticks;
185     time_t val;
186    
187     ticks = low + (((unsigned long long) high) << 32);
188     ticks /= 10000000;
189     ticks -= 11644473600LL;
190    
191     val = (time_t) ticks;
192     return (val);
193    
194     }
195    
196 astrand 785 /* A wrapper for ftruncate which supports growing files, even if the
197     native ftruncate doesn't. This is needed on Linux FAT filesystems,
198     for example. */
199     static int
200     ftruncate_growable(int fd, off_t length)
201     {
202     int ret;
203     off_t pos;
204 jsorg71 1016 static const char zero = 0;
205 n-ki 600
206 astrand 785 /* Try the simple method first */
207     if ((ret = ftruncate(fd, length)) != -1)
208     {
209     return ret;
210     }
211    
212 jsorg71 1016 /*
213 astrand 785 * Some kind of error. Perhaps we were trying to grow. Retry
214     * in a safe way.
215     */
216    
217     /* Get current position */
218     if ((pos = lseek(fd, 0, SEEK_CUR)) == -1)
219     {
220     perror("lseek");
221     return -1;
222     }
223    
224     /* Seek to new size */
225     if (lseek(fd, length, SEEK_SET) == -1)
226     {
227     perror("lseek");
228     return -1;
229     }
230    
231     /* Write a zero */
232     if (write(fd, &zero, 1) == -1)
233     {
234     perror("write");
235     return -1;
236     }
237    
238     /* Truncate. This shouldn't fail. */
239     if (ftruncate(fd, length) == -1)
240     {
241     perror("ftruncate");
242     return -1;
243     }
244    
245     /* Restore position */
246     if (lseek(fd, pos, SEEK_SET) == -1)
247     {
248     perror("lseek");
249     return -1;
250     }
251    
252     return 0;
253     }
254    
255 astrand 790 /* Just like open(2), but if a open with O_EXCL fails, retry with
256     GUARDED semantics. This might be necessary because some filesystems
257     (such as NFS filesystems mounted from a unfsd server) doesn't
258     support O_EXCL. GUARDED semantics are subject to race conditions,
259     but we can live with that.
260     */
261     static int
262     open_weak_exclusive(const char *pathname, int flags, mode_t mode)
263     {
264     int ret;
265 astrand 1401 struct stat filestat;
266 astrand 785
267 astrand 790 ret = open(pathname, flags, mode);
268     if (ret != -1 || !(flags & O_EXCL))
269     {
270     /* Success, or not using O_EXCL */
271     return ret;
272     }
273    
274     /* An error occured, and we are using O_EXCL. In case the FS
275     doesn't support O_EXCL, some kind of error will be
276     returned. Unfortunately, we don't know which one. Linux
277     2.6.8 seems to return 524, but I cannot find a documented
278     #define for this case. So, we'll return only on errors that
279     we know aren't related to O_EXCL. */
280     switch (errno)
281     {
282     case EACCES:
283     case EEXIST:
284     case EINTR:
285     case EISDIR:
286     case ELOOP:
287     case ENAMETOOLONG:
288     case ENOENT:
289     case ENOTDIR:
290     return ret;
291     }
292    
293     /* Retry with GUARDED semantics */
294 astrand 1401 if (stat(pathname, &filestat) != -1)
295 astrand 790 {
296     /* File exists */
297     errno = EEXIST;
298     return -1;
299     }
300     else
301     {
302     return open(pathname, flags & ~O_EXCL, mode);
303     }
304     }
305    
306 n-ki 569 /* Enumeration of devices from rdesktop.c */
307     /* returns numer of units found and initialized. */
308 n-ki 612 /* optarg looks like ':h=/mnt/floppy,b=/mnt/usbdevice1' */
309 n-ki 569 /* when it arrives to this function. */
310     int
311 astrand 608 disk_enum_devices(uint32 * id, char *optarg)
312 n-ki 569 {
313     char *pos = optarg;
314     char *pos2;
315     int count = 0;
316    
317 stargo 865 /* skip the first colon */
318 n-ki 569 optarg++;
319     while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
320     {
321     pos2 = next_arg(optarg, '=');
322    
323 astrand 827 strncpy(g_rdpdr_device[*id].name, optarg, sizeof(g_rdpdr_device[*id].name) - 1);
324     if (strlen(optarg) > (sizeof(g_rdpdr_device[*id].name) - 1))
325 astrand 747 fprintf(stderr, "share name %s truncated to %s\n", optarg,
326     g_rdpdr_device[*id].name);
327 n-ki 569
328 jsorg71 1016 g_rdpdr_device[*id].local_path = (char *) xmalloc(strlen(pos2) + 1);
329 n-ki 569 strcpy(g_rdpdr_device[*id].local_path, pos2);
330     g_rdpdr_device[*id].device_type = DEVICE_TYPE_DISK;
331     count++;
332     (*id)++;
333    
334     optarg = pos;
335     }
336     return count;
337     }
338    
339 n-ki 596 /* Opens or creates a file or directory */
340 jsorg71 1364 static RD_NTSTATUS
341 n-ki 569 disk_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition,
342 jsorg71 1364 uint32 flags_and_attributes, char *filename, RD_NTHANDLE * phandle)
343 n-ki 569 {
344 jsorg71 1364 RD_NTHANDLE handle;
345 n-ki 569 DIR *dirp;
346     int flags, mode;
347 stargo 978 char path[PATH_MAX];
348 n-ki 600 struct stat filestat;
349 n-ki 569
350     handle = 0;
351     dirp = NULL;
352     flags = 0;
353     mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
354    
355 astrand 787 if (*filename && filename[strlen(filename) - 1] == '/')
356 n-ki 569 filename[strlen(filename) - 1] = 0;
357     sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename);
358    
359     switch (create_disposition)
360     {
361     case CREATE_ALWAYS:
362    
363 stargo 865 /* Delete existing file/link. */
364 n-ki 569 unlink(path);
365     flags |= O_CREAT;
366     break;
367    
368     case CREATE_NEW:
369    
370 stargo 865 /* If the file already exists, then fail. */
371 n-ki 569 flags |= O_CREAT | O_EXCL;
372     break;
373    
374     case OPEN_ALWAYS:
375    
376 stargo 865 /* Create if not already exists. */
377 n-ki 569 flags |= O_CREAT;
378     break;
379    
380     case OPEN_EXISTING:
381    
382 stargo 865 /* Default behaviour */
383 n-ki 569 break;
384    
385     case TRUNCATE_EXISTING:
386    
387 stargo 865 /* If the file does not exist, then fail. */
388 n-ki 569 flags |= O_TRUNC;
389     break;
390     }
391    
392 stargo 873 /*printf("Open: \"%s\" flags: %X, accessmask: %X sharemode: %X create disp: %X\n", path, flags_and_attributes, accessmask, sharemode, create_disposition); */
393 n-ki 597
394 stargo 865 /* Get information about file and set that flag ourselfs */
395 n-ki 597 if ((stat(path, &filestat) == 0) && (S_ISDIR(filestat.st_mode)))
396 n-ki 600 {
397     if (flags_and_attributes & FILE_NON_DIRECTORY_FILE)
398 jsorg71 1364 return RD_STATUS_FILE_IS_A_DIRECTORY;
399 n-ki 600 else
400     flags_and_attributes |= FILE_DIRECTORY_FILE;
401     }
402 n-ki 597
403     if (flags_and_attributes & FILE_DIRECTORY_FILE)
404 n-ki 569 {
405 n-ki 597 if (flags & O_CREAT)
406 n-ki 569 {
407 n-ki 597 mkdir(path, mode);
408 n-ki 569 }
409    
410 n-ki 597 dirp = opendir(path);
411     if (!dirp)
412 n-ki 569 {
413     switch (errno)
414     {
415     case EACCES:
416    
417 jsorg71 1364 return RD_STATUS_ACCESS_DENIED;
418 n-ki 569
419     case ENOENT:
420    
421 jsorg71 1364 return RD_STATUS_NO_SUCH_FILE;
422 n-ki 569
423     default:
424    
425 n-ki 597 perror("opendir");
426 jsorg71 1364 return RD_STATUS_NO_SUCH_FILE;
427 n-ki 569 }
428     }
429 n-ki 597 handle = DIRFD(dirp);
430 n-ki 569 }
431 n-ki 597 else
432 n-ki 569 {
433 n-ki 596
434 n-ki 597 if (accessmask & GENERIC_ALL
435     || (accessmask & GENERIC_READ && accessmask & GENERIC_WRITE))
436 n-ki 569 {
437 n-ki 597 flags |= O_RDWR;
438 n-ki 569 }
439 n-ki 597 else if ((accessmask & GENERIC_WRITE) && !(accessmask & GENERIC_READ))
440 n-ki 569 {
441 n-ki 597 flags |= O_WRONLY;
442 n-ki 569 }
443 n-ki 597 else
444     {
445     flags |= O_RDONLY;
446     }
447 n-ki 569
448 astrand 790 handle = open_weak_exclusive(path, flags, mode);
449 n-ki 597 if (handle == -1)
450 n-ki 569 {
451     switch (errno)
452     {
453 n-ki 600 case EISDIR:
454    
455 jsorg71 1364 return RD_STATUS_FILE_IS_A_DIRECTORY;
456 n-ki 600
457 n-ki 569 case EACCES:
458    
459 jsorg71 1364 return RD_STATUS_ACCESS_DENIED;
460 n-ki 569
461     case ENOENT:
462    
463 jsorg71 1364 return RD_STATUS_NO_SUCH_FILE;
464 n-ki 612 case EEXIST:
465    
466 jsorg71 1364 return RD_STATUS_OBJECT_NAME_COLLISION;
467 n-ki 569 default:
468    
469 n-ki 597 perror("open");
470 jsorg71 1364 return RD_STATUS_NO_SUCH_FILE;
471 n-ki 569 }
472     }
473 n-ki 597
474     /* all read and writes of files should be non blocking */
475     if (fcntl(handle, F_SETFL, O_NONBLOCK) == -1)
476     perror("fcntl");
477 n-ki 569 }
478    
479     if (handle >= MAX_OPEN_FILES)
480     {
481     error("Maximum number of open files (%s) reached. Increase MAX_OPEN_FILES!\n",
482     handle);
483     exit(1);
484     }
485    
486     if (dirp)
487     g_fileinfo[handle].pdir = dirp;
488 stargo 795 else
489     g_fileinfo[handle].pdir = NULL;
490    
491 n-ki 569 g_fileinfo[handle].device_id = device_id;
492     g_fileinfo[handle].flags_and_attributes = flags_and_attributes;
493 stargo 795 g_fileinfo[handle].accessmask = accessmask;
494 astrand 986 strncpy(g_fileinfo[handle].path, path, PATH_MAX - 1);
495 stargo 795 g_fileinfo[handle].delete_on_close = False;
496 n-ki 569
497 astrand 1402 if (accessmask & GENERIC_ALL || accessmask & GENERIC_WRITE)
498     g_notify_stamp = True;
499    
500 n-ki 569 *phandle = handle;
501 jsorg71 1364 return RD_STATUS_SUCCESS;
502 n-ki 569 }
503    
504 jsorg71 1364 static RD_NTSTATUS
505     disk_close(RD_NTHANDLE handle)
506 n-ki 569 {
507     struct fileinfo *pfinfo;
508    
509     pfinfo = &(g_fileinfo[handle]);
510    
511 astrand 1402 if (pfinfo->accessmask & GENERIC_ALL || pfinfo->accessmask & GENERIC_WRITE)
512     g_notify_stamp = True;
513 stargo 795
514 jsorg71 1364 rdpdr_abort_io(handle, 0, RD_STATUS_CANCELLED);
515 stargo 795
516     if (pfinfo->pdir)
517 n-ki 569 {
518 stargo 795 if (closedir(pfinfo->pdir) < 0)
519     {
520     perror("closedir");
521 jsorg71 1364 return RD_STATUS_INVALID_HANDLE;
522 stargo 795 }
523    
524     if (pfinfo->delete_on_close)
525     if (rmdir(pfinfo->path) < 0)
526     {
527     perror(pfinfo->path);
528 jsorg71 1364 return RD_STATUS_ACCESS_DENIED;
529 stargo 795 }
530     pfinfo->delete_on_close = False;
531 n-ki 569 }
532     else
533     {
534 stargo 795 if (close(handle) < 0)
535     {
536     perror("close");
537 jsorg71 1364 return RD_STATUS_INVALID_HANDLE;
538 stargo 795 }
539     if (pfinfo->delete_on_close)
540     if (unlink(pfinfo->path) < 0)
541     {
542     perror(pfinfo->path);
543 jsorg71 1364 return RD_STATUS_ACCESS_DENIED;
544 stargo 795 }
545    
546     pfinfo->delete_on_close = False;
547 n-ki 569 }
548    
549 jsorg71 1364 return RD_STATUS_SUCCESS;
550 n-ki 569 }
551    
552 jsorg71 1364 static RD_NTSTATUS
553     disk_read(RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
554 n-ki 569 {
555     int n;
556    
557 n-ki 600 #if 0
558 n-ki 596 /* browsing dir ???? */
559     /* each request is 24 bytes */
560     if (g_fileinfo[handle].flags_and_attributes & FILE_DIRECTORY_FILE)
561     {
562     *result = 0;
563     return STATUS_SUCCESS;
564     }
565 n-ki 600 #endif
566 n-ki 596
567 n-ki 613 lseek(handle, offset, SEEK_SET);
568    
569 n-ki 569 n = read(handle, data, length);
570    
571     if (n < 0)
572     {
573     *result = 0;
574 n-ki 600 switch (errno)
575     {
576     case EISDIR:
577 stargo 795 /* Implement 24 Byte directory read ??
578     with STATUS_NOT_IMPLEMENTED server doesn't read again */
579     /* return STATUS_FILE_IS_A_DIRECTORY; */
580 jsorg71 1364 return RD_STATUS_NOT_IMPLEMENTED;
581 n-ki 600 default:
582     perror("read");
583 jsorg71 1364 return RD_STATUS_INVALID_PARAMETER;
584 n-ki 600 }
585 n-ki 569 }
586    
587     *result = n;
588    
589 jsorg71 1364 return RD_STATUS_SUCCESS;
590 n-ki 569 }
591    
592 jsorg71 1364 static RD_NTSTATUS
593     disk_write(RD_NTHANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
594 n-ki 569 {
595     int n;
596    
597 n-ki 613 lseek(handle, offset, SEEK_SET);
598 n-ki 569
599     n = write(handle, data, length);
600    
601     if (n < 0)
602     {
603     perror("write");
604     *result = 0;
605 n-ki 600 switch (errno)
606     {
607     case ENOSPC:
608 jsorg71 1364 return RD_STATUS_DISK_FULL;
609 n-ki 600 default:
610 jsorg71 1364 return RD_STATUS_ACCESS_DENIED;
611 n-ki 600 }
612 n-ki 569 }
613    
614     *result = n;
615    
616 jsorg71 1364 return RD_STATUS_SUCCESS;
617 n-ki 569 }
618    
619 jsorg71 1364 RD_NTSTATUS
620     disk_query_information(RD_NTHANDLE handle, uint32 info_class, STREAM out)
621 n-ki 569 {
622     uint32 file_attributes, ft_high, ft_low;
623     struct stat filestat;
624     char *path, *filename;
625    
626     path = g_fileinfo[handle].path;
627    
628 stargo 865 /* Get information about file */
629 n-ki 569 if (fstat(handle, &filestat) != 0)
630     {
631     perror("stat");
632     out_uint8(out, 0);
633 jsorg71 1364 return RD_STATUS_ACCESS_DENIED;
634 n-ki 569 }
635    
636 stargo 865 /* Set file attributes */
637 n-ki 569 file_attributes = 0;
638     if (S_ISDIR(filestat.st_mode))
639     file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
640 n-ki 600
641 n-ki 569 filename = 1 + strrchr(path, '/');
642     if (filename && filename[0] == '.')
643     file_attributes |= FILE_ATTRIBUTE_HIDDEN;
644    
645 n-ki 600 if (!file_attributes)
646     file_attributes |= FILE_ATTRIBUTE_NORMAL;
647    
648     if (!(filestat.st_mode & S_IWUSR))
649     file_attributes |= FILE_ATTRIBUTE_READONLY;
650    
651 stargo 865 /* Return requested data */
652 n-ki 569 switch (info_class)
653     {
654 astrand 653 case FileBasicInformation:
655 n-ki 600 seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high,
656     &ft_low);
657 stargo 865 out_uint32_le(out, ft_low); /* create_access_time */
658 n-ki 600 out_uint32_le(out, ft_high);
659 n-ki 569
660     seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low);
661 stargo 865 out_uint32_le(out, ft_low); /* last_access_time */
662 n-ki 569 out_uint32_le(out, ft_high);
663    
664     seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low);
665 stargo 865 out_uint32_le(out, ft_low); /* last_write_time */
666 n-ki 569 out_uint32_le(out, ft_high);
667    
668 n-ki 600 seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low);
669 stargo 865 out_uint32_le(out, ft_low); /* last_change_time */
670 n-ki 600 out_uint32_le(out, ft_high);
671    
672 n-ki 569 out_uint32_le(out, file_attributes);
673     break;
674    
675 astrand 653 case FileStandardInformation:
676 n-ki 569
677 stargo 865 out_uint32_le(out, filestat.st_size); /* Allocation size */
678 n-ki 569 out_uint32_le(out, 0);
679 stargo 865 out_uint32_le(out, filestat.st_size); /* End of file */
680 n-ki 569 out_uint32_le(out, 0);
681 stargo 865 out_uint32_le(out, filestat.st_nlink); /* Number of links */
682     out_uint8(out, 0); /* Delete pending */
683     out_uint8(out, S_ISDIR(filestat.st_mode) ? 1 : 0); /* Directory */
684 n-ki 569 break;
685    
686 astrand 653 case FileObjectIdInformation:
687 n-ki 569
688     out_uint32_le(out, file_attributes); /* File Attributes */
689     out_uint32_le(out, 0); /* Reparse Tag */
690     break;
691    
692     default:
693    
694     unimpl("IRP Query (File) Information class: 0x%x\n", info_class);
695 jsorg71 1364 return RD_STATUS_INVALID_PARAMETER;
696 n-ki 569 }
697 jsorg71 1364 return RD_STATUS_SUCCESS;
698 n-ki 569 }
699    
700 jsorg71 1364 RD_NTSTATUS
701     disk_set_information(RD_NTHANDLE handle, uint32 info_class, STREAM in, STREAM out)
702 n-ki 569 {
703 stargo 795 uint32 length, file_attributes, ft_high, ft_low, delete_on_close;
704 stargo 978 char newname[PATH_MAX], fullpath[PATH_MAX];
705 n-ki 569 struct fileinfo *pfinfo;
706 n-ki 600 int mode;
707     struct stat filestat;
708     time_t write_time, change_time, access_time, mod_time;
709     struct utimbuf tvs;
710 n-ki 612 struct STATFS_T stat_fs;
711 n-ki 600
712 n-ki 569 pfinfo = &(g_fileinfo[handle]);
713 stargo 795 g_notify_stamp = True;
714 n-ki 569
715     switch (info_class)
716     {
717 astrand 653 case FileBasicInformation:
718 n-ki 600 write_time = change_time = access_time = 0;
719 n-ki 569
720 n-ki 600 in_uint8s(in, 4); /* Handle of root dir? */
721     in_uint8s(in, 24); /* unknown */
722    
723 stargo 865 /* CreationTime */
724 n-ki 600 in_uint32_le(in, ft_low);
725     in_uint32_le(in, ft_high);
726    
727 stargo 865 /* AccessTime */
728 n-ki 600 in_uint32_le(in, ft_low);
729     in_uint32_le(in, ft_high);
730     if (ft_low || ft_high)
731     access_time = convert_1970_to_filetime(ft_high, ft_low);
732    
733 stargo 865 /* WriteTime */
734 n-ki 600 in_uint32_le(in, ft_low);
735     in_uint32_le(in, ft_high);
736     if (ft_low || ft_high)
737     write_time = convert_1970_to_filetime(ft_high, ft_low);
738    
739 stargo 865 /* ChangeTime */
740 n-ki 600 in_uint32_le(in, ft_low);
741     in_uint32_le(in, ft_high);
742     if (ft_low || ft_high)
743     change_time = convert_1970_to_filetime(ft_high, ft_low);
744    
745     in_uint32_le(in, file_attributes);
746    
747     if (fstat(handle, &filestat))
748 jsorg71 1364 return RD_STATUS_ACCESS_DENIED;
749 n-ki 600
750     tvs.modtime = filestat.st_mtime;
751     tvs.actime = filestat.st_atime;
752     if (access_time)
753     tvs.actime = access_time;
754    
755    
756     if (write_time || change_time)
757     mod_time = MIN(write_time, change_time);
758     else
759     mod_time = write_time ? write_time : change_time;
760    
761     if (mod_time)
762     tvs.modtime = mod_time;
763    
764    
765     if (access_time || write_time || change_time)
766     {
767     #if WITH_DEBUG_RDP5
768     printf("FileBasicInformation access time %s",
769     ctime(&tvs.actime));
770     printf("FileBasicInformation modification time %s",
771     ctime(&tvs.modtime));
772     #endif
773 stargo 795 if (utime(pfinfo->path, &tvs) && errno != EPERM)
774 jsorg71 1364 return RD_STATUS_ACCESS_DENIED;
775 n-ki 600 }
776    
777     if (!file_attributes)
778 stargo 865 break; /* not valid */
779 n-ki 600
780     mode = filestat.st_mode;
781    
782     if (file_attributes & FILE_ATTRIBUTE_READONLY)
783     mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
784     else
785     mode |= S_IWUSR;
786    
787     mode &= 0777;
788     #if WITH_DEBUG_RDP5
789     printf("FileBasicInformation set access mode 0%o", mode);
790     #endif
791    
792     if (fchmod(handle, mode))
793 jsorg71 1364 return RD_STATUS_ACCESS_DENIED;
794 n-ki 612
795 n-ki 569 break;
796    
797 astrand 653 case FileRenameInformation:
798 n-ki 569
799     in_uint8s(in, 4); /* Handle of root dir? */
800     in_uint8s(in, 0x1a); /* unknown */
801     in_uint32_le(in, length);
802    
803     if (length && (length / 2) < 256)
804     {
805 matthewc 1426 rdp_in_unistr(in, newname, sizeof(newname), length);
806 n-ki 569 convert_to_unix_filename(newname);
807     }
808     else
809     {
810 jsorg71 1364 return RD_STATUS_INVALID_PARAMETER;
811 n-ki 569 }
812    
813     sprintf(fullpath, "%s%s", g_rdpdr_device[pfinfo->device_id].local_path,
814     newname);
815    
816     if (rename(pfinfo->path, fullpath) != 0)
817     {
818     perror("rename");
819 jsorg71 1364 return RD_STATUS_ACCESS_DENIED;
820 n-ki 569 }
821     break;
822    
823 astrand 653 case FileDispositionInformation:
824 astrand 659 /* As far as I understand it, the correct
825     thing to do here is to *schedule* a delete,
826     so it will be deleted when the file is
827     closed. Subsequent
828     FileDispositionInformation requests with
829     DeleteFile set to FALSE should unschedule
830     the delete. See
831 stargo 795 http://www.osronline.com/article.cfm?article=245. */
832 n-ki 569
833 stargo 795 in_uint32_le(in, delete_on_close);
834 n-ki 601
835 stargo 795 if (delete_on_close ||
836     (pfinfo->
837     accessmask & (FILE_DELETE_ON_CLOSE | FILE_COMPLETE_IF_OPLOCKED)))
838 n-ki 601 {
839 stargo 795 pfinfo->delete_on_close = True;
840 n-ki 601 }
841    
842 n-ki 569 break;
843    
844 astrand 653 case FileAllocationInformation:
845 astrand 661 /* Fall through to FileEndOfFileInformation,
846     which uses ftrunc. This is like Samba with
847     "strict allocation = false", and means that
848     we won't detect out-of-quota errors, for
849     example. */
850 n-ki 569
851 astrand 653 case FileEndOfFileInformation:
852 n-ki 600 in_uint8s(in, 28); /* unknown */
853     in_uint32_le(in, length); /* file size */
854 n-ki 569
855 n-ki 616 /* prevents start of writing if not enough space left on device */
856 matthewc 1435 if (STATFS_FN(pfinfo->path, &stat_fs) == 0)
857 stargo 795 if (stat_fs.f_bfree * stat_fs.f_bsize < length)
858 jsorg71 1364 return RD_STATUS_DISK_FULL;
859 n-ki 616
860 astrand 785 if (ftruncate_growable(handle, length) != 0)
861 astrand 661 {
862 jsorg71 1364 return RD_STATUS_DISK_FULL;
863 astrand 661 }
864    
865 n-ki 569 break;
866     default:
867    
868     unimpl("IRP Set File Information class: 0x%x\n", info_class);
869 jsorg71 1364 return RD_STATUS_INVALID_PARAMETER;
870 n-ki 569 }
871 jsorg71 1364 return RD_STATUS_SUCCESS;
872 n-ki 569 }
873    
874 jsorg71 1364 RD_NTSTATUS
875     disk_check_notify(RD_NTHANDLE handle)
876 stargo 795 {
877     struct fileinfo *pfinfo;
878 jsorg71 1364 RD_NTSTATUS status = RD_STATUS_PENDING;
879 stargo 795
880     NOTIFY notify;
881    
882     pfinfo = &(g_fileinfo[handle]);
883     if (!pfinfo->pdir)
884 jsorg71 1364 return RD_STATUS_INVALID_DEVICE_REQUEST;
885 stargo 795
886    
887    
888     status = NotifyInfo(handle, pfinfo->info_class, &notify);
889    
890 jsorg71 1364 if (status != RD_STATUS_PENDING)
891 stargo 795 return status;
892    
893     if (memcmp(&pfinfo->notify, &notify, sizeof(NOTIFY)))
894     {
895 stargo 873 /*printf("disk_check_notify found changed event\n"); */
896 stargo 795 memcpy(&pfinfo->notify, &notify, sizeof(NOTIFY));
897 jsorg71 1364 status = RD_STATUS_NOTIFY_ENUM_DIR;
898 stargo 795 }
899    
900     return status;
901    
902    
903     }
904    
905 jsorg71 1364 RD_NTSTATUS
906     disk_create_notify(RD_NTHANDLE handle, uint32 info_class)
907 stargo 795 {
908    
909     struct fileinfo *pfinfo;
910 jsorg71 1364 RD_NTSTATUS ret = RD_STATUS_PENDING;
911 stargo 795
912     /* printf("start disk_create_notify info_class %X\n", info_class); */
913    
914     pfinfo = &(g_fileinfo[handle]);
915     pfinfo->info_class = info_class;
916    
917     ret = NotifyInfo(handle, info_class, &pfinfo->notify);
918    
919     if (info_class & 0x1000)
920     { /* ???? */
921 jsorg71 1364 if (ret == RD_STATUS_PENDING)
922     return RD_STATUS_SUCCESS;
923 stargo 795 }
924    
925     /* printf("disk_create_notify: num_entries %d\n", pfinfo->notify.num_entries); */
926    
927    
928     return ret;
929    
930     }
931    
932 jsorg71 1364 static RD_NTSTATUS
933     NotifyInfo(RD_NTHANDLE handle, uint32 info_class, NOTIFY * p)
934 stargo 795 {
935     struct fileinfo *pfinfo;
936 astrand 1401 struct stat filestat;
937 stargo 795 struct dirent *dp;
938     char *fullname;
939     DIR *dpr;
940    
941     pfinfo = &(g_fileinfo[handle]);
942 astrand 1401 if (fstat(handle, &filestat) < 0)
943 stargo 795 {
944     perror("NotifyInfo");
945 jsorg71 1364 return RD_STATUS_ACCESS_DENIED;
946 stargo 795 }
947 astrand 1401 p->modify_time = filestat.st_mtime;
948     p->status_time = filestat.st_ctime;
949 stargo 795 p->num_entries = 0;
950     p->total_time = 0;
951    
952    
953     dpr = opendir(pfinfo->path);
954     if (!dpr)
955     {
956     perror("NotifyInfo");
957 jsorg71 1364 return RD_STATUS_ACCESS_DENIED;
958 stargo 795 }
959    
960    
961     while ((dp = readdir(dpr)))
962     {
963     if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
964     continue;
965     p->num_entries++;
966 jsorg71 1016 fullname = (char *) xmalloc(strlen(pfinfo->path) + strlen(dp->d_name) + 2);
967 stargo 795 sprintf(fullname, "%s/%s", pfinfo->path, dp->d_name);
968    
969 astrand 1401 if (!stat(fullname, &filestat))
970 stargo 795 {
971 astrand 1401 p->total_time += (filestat.st_mtime + filestat.st_ctime);
972 stargo 795 }
973    
974     xfree(fullname);
975     }
976     closedir(dpr);
977    
978 jsorg71 1364 return RD_STATUS_PENDING;
979 stargo 795 }
980    
981 astrand 664 static FsInfoType *
982 n-ki 615 FsVolumeInfo(char *fpath)
983     {
984    
985 stargo 795 static FsInfoType info;
986 stargo 873 #ifdef USE_SETMNTENT
987 stargo 832 FILE *fdfs;
988 n-ki 615 struct mntent *e;
989 stargo 795 #endif
990 n-ki 615
991     /* initialize */
992     memset(&info, 0, sizeof(info));
993     strcpy(info.label, "RDESKTOP");
994     strcpy(info.type, "RDPFS");
995    
996 stargo 873 #ifdef USE_SETMNTENT
997 n-ki 615 fdfs = setmntent(MNTENT_PATH, "r");
998     if (!fdfs)
999     return &info;
1000    
1001     while ((e = getmntent(fdfs)))
1002     {
1003 astrand 1010 if (str_startswith(e->mnt_dir, fpath))
1004 n-ki 615 {
1005     strcpy(info.type, e->mnt_type);
1006     strcpy(info.name, e->mnt_fsname);
1007     if (strstr(e->mnt_opts, "vfat") || strstr(e->mnt_opts, "iso9660"))
1008     {
1009     int fd = open(e->mnt_fsname, O_RDONLY);
1010     if (fd >= 0)
1011     {
1012     unsigned char buf[512];
1013     memset(buf, 0, sizeof(buf));
1014     if (strstr(e->mnt_opts, "vfat"))
1015     /*FAT*/
1016     {
1017     strcpy(info.type, "vfat");
1018     read(fd, buf, sizeof(buf));
1019     info.serial =
1020     (buf[42] << 24) + (buf[41] << 16) +
1021     (buf[40] << 8) + buf[39];
1022 astrand 1242 strncpy(info.label, (char *) buf + 43, 10);
1023 n-ki 615 info.label[10] = '\0';
1024     }
1025     else if (lseek(fd, 32767, SEEK_SET) >= 0) /* ISO9660 */
1026     {
1027     read(fd, buf, sizeof(buf));
1028 astrand 1242 strncpy(info.label, (char *) buf + 41, 32);
1029 n-ki 615 info.label[32] = '\0';
1030 stargo 865 /* info.Serial = (buf[128]<<24)+(buf[127]<<16)+(buf[126]<<8)+buf[125]; */
1031 n-ki 615 }
1032     close(fd);
1033     }
1034     }
1035     }
1036     }
1037     endmntent(fdfs);
1038     #else
1039     /* initialize */
1040     memset(&info, 0, sizeof(info));
1041     strcpy(info.label, "RDESKTOP");
1042     strcpy(info.type, "RDPFS");
1043    
1044     #endif
1045     return &info;
1046     }
1047    
1048    
1049 jsorg71 1364 RD_NTSTATUS
1050     disk_query_volume_information(RD_NTHANDLE handle, uint32 info_class, STREAM out)
1051 n-ki 569 {
1052 stargo 574 struct STATFS_T stat_fs;
1053 n-ki 569 struct fileinfo *pfinfo;
1054 n-ki 615 FsInfoType *fsinfo;
1055 n-ki 569
1056     pfinfo = &(g_fileinfo[handle]);
1057    
1058 n-ki 600 if (STATFS_FN(pfinfo->path, &stat_fs) != 0)
1059 n-ki 569 {
1060     perror("statfs");
1061 jsorg71 1364 return RD_STATUS_ACCESS_DENIED;
1062 n-ki 569 }
1063    
1064 n-ki 615 fsinfo = FsVolumeInfo(pfinfo->path);
1065    
1066 n-ki 569 switch (info_class)
1067     {
1068 astrand 653 case FileFsVolumeInformation:
1069 n-ki 569
1070     out_uint32_le(out, 0); /* volume creation time low */
1071     out_uint32_le(out, 0); /* volume creation time high */
1072 n-ki 615 out_uint32_le(out, fsinfo->serial); /* serial */
1073    
1074     out_uint32_le(out, 2 * strlen(fsinfo->label)); /* length of string */
1075    
1076 n-ki 569 out_uint8(out, 0); /* support objects? */
1077 n-ki 615 rdp_out_unistr(out, fsinfo->label, 2 * strlen(fsinfo->label) - 2);
1078 n-ki 569 break;
1079    
1080 astrand 653 case FileFsSizeInformation:
1081 n-ki 569
1082     out_uint32_le(out, stat_fs.f_blocks); /* Total allocation units low */
1083     out_uint32_le(out, 0); /* Total allocation high units */
1084     out_uint32_le(out, stat_fs.f_bfree); /* Available allocation units */
1085     out_uint32_le(out, 0); /* Available allowcation units */
1086     out_uint32_le(out, stat_fs.f_bsize / 0x200); /* Sectors per allocation unit */
1087     out_uint32_le(out, 0x200); /* Bytes per sector */
1088     break;
1089    
1090 astrand 653 case FileFsAttributeInformation:
1091 n-ki 569
1092     out_uint32_le(out, FS_CASE_SENSITIVE | FS_CASE_IS_PRESERVED); /* fs attributes */
1093 stargo 574 out_uint32_le(out, F_NAMELEN(stat_fs)); /* max length of filename */
1094 n-ki 615
1095     out_uint32_le(out, 2 * strlen(fsinfo->type)); /* length of fs_type */
1096     rdp_out_unistr(out, fsinfo->type, 2 * strlen(fsinfo->type) - 2);
1097 n-ki 569 break;
1098    
1099 astrand 653 case FileFsLabelInformation:
1100     case FileFsDeviceInformation:
1101     case FileFsControlInformation:
1102     case FileFsFullSizeInformation:
1103     case FileFsObjectIdInformation:
1104     case FileFsMaximumInformation:
1105    
1106 n-ki 569 default:
1107    
1108     unimpl("IRP Query Volume Information class: 0x%x\n", info_class);
1109 jsorg71 1364 return RD_STATUS_INVALID_PARAMETER;
1110 n-ki 569 }
1111 jsorg71 1364 return RD_STATUS_SUCCESS;
1112 n-ki 569 }
1113    
1114 jsorg71 1364 RD_NTSTATUS
1115     disk_query_directory(RD_NTHANDLE handle, uint32 info_class, char *pattern, STREAM out)
1116 n-ki 569 {
1117     uint32 file_attributes, ft_low, ft_high;
1118 stargo 978 char *dirname, fullpath[PATH_MAX];
1119 n-ki 569 DIR *pdir;
1120     struct dirent *pdirent;
1121 astrand 1401 struct stat filestat;
1122 n-ki 569 struct fileinfo *pfinfo;
1123    
1124     pfinfo = &(g_fileinfo[handle]);
1125     pdir = pfinfo->pdir;
1126     dirname = pfinfo->path;
1127     file_attributes = 0;
1128    
1129     switch (info_class)
1130     {
1131 astrand 696 case FileBothDirectoryInformation:
1132 n-ki 569
1133 stargo 865 /* If a search pattern is received, remember this pattern, and restart search */
1134 n-ki 569 if (pattern[0] != 0)
1135     {
1136 astrand 986 strncpy(pfinfo->pattern, 1 + strrchr(pattern, '/'), PATH_MAX - 1);
1137 n-ki 569 rewinddir(pdir);
1138     }
1139    
1140 stargo 865 /* find next dirent matching pattern */
1141 n-ki 569 pdirent = readdir(pdir);
1142     while (pdirent && fnmatch(pfinfo->pattern, pdirent->d_name, 0) != 0)
1143     pdirent = readdir(pdir);
1144    
1145     if (pdirent == NULL)
1146 jsorg71 1364 return RD_STATUS_NO_MORE_FILES;
1147 n-ki 569
1148 stargo 865 /* Get information for directory entry */
1149 n-ki 569 sprintf(fullpath, "%s/%s", dirname, pdirent->d_name);
1150 n-ki 600
1151 astrand 1401 if (stat(fullpath, &filestat))
1152 n-ki 569 {
1153 astrand 698 switch (errno)
1154     {
1155     case ENOENT:
1156     case ELOOP:
1157     case EACCES:
1158     /* These are non-fatal errors. */
1159 astrand 1401 memset(&filestat, 0, sizeof(filestat));
1160 astrand 698 break;
1161     default:
1162     /* Fatal error. By returning STATUS_NO_SUCH_FILE,
1163     the directory list operation will be aborted */
1164     perror(fullpath);
1165     out_uint8(out, 0);
1166 jsorg71 1364 return RD_STATUS_NO_SUCH_FILE;
1167 astrand 698 }
1168 n-ki 569 }
1169    
1170 astrand 1401 if (S_ISDIR(filestat.st_mode))
1171 n-ki 569 file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
1172     if (pdirent->d_name[0] == '.')
1173     file_attributes |= FILE_ATTRIBUTE_HIDDEN;
1174 n-ki 600 if (!file_attributes)
1175     file_attributes |= FILE_ATTRIBUTE_NORMAL;
1176 astrand 1401 if (!(filestat.st_mode & S_IWUSR))
1177 n-ki 600 file_attributes |= FILE_ATTRIBUTE_READONLY;
1178 n-ki 569
1179 stargo 865 /* Return requested information */
1180     out_uint8s(out, 8); /* unknown zero */
1181 n-ki 569
1182 astrand 1401 seconds_since_1970_to_filetime(get_create_time(&filestat), &ft_high,
1183     &ft_low);
1184 stargo 865 out_uint32_le(out, ft_low); /* create time */
1185 n-ki 600 out_uint32_le(out, ft_high);
1186    
1187 astrand 1401 seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low);
1188 stargo 865 out_uint32_le(out, ft_low); /* last_access_time */
1189 n-ki 569 out_uint32_le(out, ft_high);
1190    
1191 astrand 1401 seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low);
1192 stargo 865 out_uint32_le(out, ft_low); /* last_write_time */
1193 n-ki 569 out_uint32_le(out, ft_high);
1194    
1195 astrand 1401 seconds_since_1970_to_filetime(filestat.st_ctime, &ft_high, &ft_low);
1196 stargo 865 out_uint32_le(out, ft_low); /* change_write_time */
1197 n-ki 600 out_uint32_le(out, ft_high);
1198    
1199 astrand 1401 out_uint32_le(out, filestat.st_size); /* filesize low */
1200 stargo 865 out_uint32_le(out, 0); /* filesize high */
1201 astrand 1401 out_uint32_le(out, filestat.st_size); /* filesize low */
1202 stargo 865 out_uint32_le(out, 0); /* filesize high */
1203 n-ki 569 out_uint32_le(out, file_attributes);
1204 stargo 865 out_uint8(out, 2 * strlen(pdirent->d_name) + 2); /* unicode length */
1205     out_uint8s(out, 7); /* pad? */
1206     out_uint8(out, 0); /* 8.3 file length */
1207     out_uint8s(out, 2 * 12); /* 8.3 unicode length */
1208 n-ki 569 rdp_out_unistr(out, pdirent->d_name, 2 * strlen(pdirent->d_name));
1209     break;
1210    
1211     default:
1212 astrand 696 /* FIXME: Support FileDirectoryInformation,
1213     FileFullDirectoryInformation, and
1214     FileNamesInformation */
1215 n-ki 569
1216     unimpl("IRP Query Directory sub: 0x%x\n", info_class);
1217 jsorg71 1364 return RD_STATUS_INVALID_PARAMETER;
1218 n-ki 569 }
1219    
1220 jsorg71 1364 return RD_STATUS_SUCCESS;
1221 n-ki 569 }
1222    
1223 n-ki 600
1224    
1225 jsorg71 1364 static RD_NTSTATUS
1226     disk_device_control(RD_NTHANDLE handle, uint32 request, STREAM in, STREAM out)
1227 n-ki 600 {
1228     if (((request >> 16) != 20) || ((request >> 16) != 9))
1229 jsorg71 1364 return RD_STATUS_INVALID_PARAMETER;
1230 n-ki 600
1231     /* extract operation */
1232     request >>= 2;
1233     request &= 0xfff;
1234    
1235     printf("DISK IOCTL %d\n", request);
1236    
1237     switch (request)
1238     {
1239 stargo 865 case 25: /* ? */
1240     case 42: /* ? */
1241 n-ki 600 default:
1242     unimpl("DISK IOCTL %d\n", request);
1243 jsorg71 1364 return RD_STATUS_INVALID_PARAMETER;
1244 n-ki 600 }
1245    
1246 jsorg71 1364 return RD_STATUS_SUCCESS;
1247 n-ki 600 }
1248    
1249 n-ki 569 DEVICE_FNS disk_fns = {
1250     disk_create,
1251     disk_close,
1252     disk_read,
1253     disk_write,
1254 n-ki 600 disk_device_control /* device_control */
1255 n-ki 569 };

  ViewVC Help
Powered by ViewVC 1.1.26