/[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 570 - (hide annotations)
Wed Jan 21 18:02:38 2004 UTC (20 years, 4 months ago) by stargo
File MIME type: text/plain
File size: 15225 byte(s)
some fixes for solaris compiles.
toupper was redefined to handle strings, now renamed to toupper_str
disk.c has some more problems (it uses statfs and dirfd)

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     #define FILE_ATTRIBUTE_NORMAL 0x00000080
28     #define FILE_ATTRIBUTE_TEMPORARY 0x00000100
29     #define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
30     #define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
31     #define FILE_ATTRIBUTE_COMPRESSED 0x00000800
32     #define FILE_ATTRIBUTE_OFFLINE 0x00001000
33     #define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
34     #define FILE_ATTRIBUTE_ENCRYPTED 0x00004000
35    
36     #define FILE_BASIC_INFORMATION 0x04
37     #define FILE_STANDARD_INFORMATION 0x05
38    
39     #define FS_CASE_SENSITIVE 0x00000001
40     #define FS_CASE_IS_PRESERVED 0x00000002
41     #define FS_UNICODE_STORED_ON_DISK 0x00000004
42     #define FS_PERSISTENT_ACLS 0x00000008
43     #define FS_FILE_COMPRESSION 0x00000010
44     #define FS_VOLUME_QUOTAS 0x00000020
45     #define FS_SUPPORTS_SPARSE_FILES 0x00000040
46     #define FS_SUPPORTS_REPARSE_POINTS 0x00000080
47     #define FS_SUPPORTS_REMOTE_STORAGE 0X00000100
48     #define FS_VOL_IS_COMPRESSED 0x00008000
49     #define FILE_READ_ONLY_VOLUME 0x00080000
50    
51     #define OPEN_EXISTING 1
52     #define CREATE_NEW 2
53     #define OPEN_ALWAYS 3
54     #define TRUNCATE_EXISTING 4
55     #define CREATE_ALWAYS 5
56    
57     #define GENERIC_READ 0x80000000
58     #define GENERIC_WRITE 0x40000000
59     #define GENERIC_EXECUTE 0x20000000
60     #define GENERIC_ALL 0x10000000
61    
62     #define ERROR_FILE_NOT_FOUND 2L
63     #define ERROR_ALREADY_EXISTS 183L
64    
65     #define MAX_OPEN_FILES 0x100
66    
67     #include <sys/types.h>
68     #include <sys/stat.h>
69     #include <sys/vfs.h> /* linux statfs */
70     #include <unistd.h>
71     #include <fcntl.h> /* open, close */
72     #include <dirent.h> /* opendir, closedir, readdir */
73     #include <fnmatch.h>
74     #include <errno.h> /* errno */
75     #include "rdesktop.h"
76    
77     extern RDPDR_DEVICE g_rdpdr_device[];
78    
79     struct fileinfo
80     {
81     uint32 device_id, flags_and_attributes;
82     char path[256];
83     DIR *pdir;
84     struct dirent *pdirent;
85     char pattern[64];
86     BOOL delete_on_close;
87     }
88     g_fileinfo[MAX_OPEN_FILES];
89    
90     /* Convert seconds since 1970 to a filetime */
91     void
92     seconds_since_1970_to_filetime(time_t seconds, uint32 * high, uint32 * low)
93     {
94     unsigned long long ticks;
95    
96     ticks = (seconds + 11644473600LL) * 10000000;
97     *low = (uint32) ticks;
98     *high = (uint32) (ticks >> 32);
99     }
100    
101     /* Enumeration of devices from rdesktop.c */
102     /* returns numer of units found and initialized. */
103     /* optarg looks like ':h:=/mnt/floppy,b:=/mnt/usbdevice1' */
104     /* when it arrives to this function. */
105     int
106     disk_enum_devices(int *id, char *optarg)
107     {
108     char *pos = optarg;
109     char *pos2;
110     int count = 0;
111    
112     // skip the first colon
113     optarg++;
114     while ((pos = next_arg(optarg, ',')) && *id < RDPDR_MAX_DEVICES)
115     {
116     pos2 = next_arg(optarg, '=');
117     strcpy(g_rdpdr_device[*id].name, optarg);
118    
119 stargo 570 toupper_str(g_rdpdr_device[*id].name);
120 n-ki 569
121     /* add trailing colon to name. */
122     strcat(g_rdpdr_device[*id].name, ":");
123    
124     g_rdpdr_device[*id].local_path = xmalloc(strlen(pos2) + 1);
125     strcpy(g_rdpdr_device[*id].local_path, pos2);
126     printf("DISK %s to %s\n", g_rdpdr_device[*id].name, g_rdpdr_device[*id].local_path);
127     g_rdpdr_device[*id].device_type = DEVICE_TYPE_DISK;
128     count++;
129     (*id)++;
130    
131     optarg = pos;
132     }
133     return count;
134     }
135    
136     /* Opens of creates a file or directory */
137     NTSTATUS
138     disk_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition,
139     uint32 flags_and_attributes, char *filename, HANDLE * phandle)
140     {
141     HANDLE handle;
142     DIR *dirp;
143     int flags, mode;
144     char path[256];
145    
146     handle = 0;
147     dirp = NULL;
148     flags = 0;
149     mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
150    
151     if (filename[strlen(filename) - 1] == '/')
152     filename[strlen(filename) - 1] = 0;
153     sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename);
154     //printf("Open: %s\n", path);
155    
156     switch (create_disposition)
157     {
158     case CREATE_ALWAYS:
159    
160     // Delete existing file/link.
161     unlink(path);
162     flags |= O_CREAT;
163     break;
164    
165     case CREATE_NEW:
166    
167     // If the file already exists, then fail.
168     flags |= O_CREAT | O_EXCL;
169     break;
170    
171     case OPEN_ALWAYS:
172    
173     // Create if not already exists.
174     flags |= O_CREAT;
175     break;
176    
177     case OPEN_EXISTING:
178    
179     // Default behaviour
180     break;
181    
182     case TRUNCATE_EXISTING:
183    
184     // If the file does not exist, then fail.
185     flags |= O_TRUNC;
186     break;
187     }
188    
189     if (flags_and_attributes & FILE_DIRECTORY_FILE)
190     {
191     if (flags & O_CREAT)
192     {
193     mkdir(path, mode);
194     }
195    
196     dirp = opendir(path);
197     if (!dirp)
198     {
199     switch (errno)
200     {
201     case EACCES:
202    
203     return STATUS_ACCESS_DENIED;
204    
205     case ENOENT:
206    
207     return STATUS_NO_SUCH_FILE;
208    
209     default:
210    
211     perror("opendir");
212     return STATUS_NO_SUCH_FILE;
213     }
214     }
215 stargo 570 handle = dirfd(dirp); /* FIXME: dirfd is not portable */
216 n-ki 569 }
217     else
218     {
219     if (accessmask & GENERIC_ALL
220     || (accessmask & GENERIC_READ && accessmask & GENERIC_WRITE))
221     {
222     flags |= O_RDWR;
223     }
224     else if ((accessmask & GENERIC_WRITE) && !(accessmask & GENERIC_READ))
225     {
226     flags |= O_WRONLY;
227     }
228     else
229     {
230     flags |= O_RDONLY;
231     }
232    
233     handle = open(path, flags, mode);
234     if (handle == -1)
235     {
236     switch (errno)
237     {
238     case EACCES:
239    
240     return STATUS_ACCESS_DENIED;
241    
242     case ENOENT:
243    
244     return STATUS_NO_SUCH_FILE;
245    
246     default:
247    
248     perror("open");
249     return STATUS_NO_SUCH_FILE;
250     }
251     }
252     }
253    
254     if (handle >= MAX_OPEN_FILES)
255     {
256     error("Maximum number of open files (%s) reached. Increase MAX_OPEN_FILES!\n",
257     handle);
258     exit(1);
259     }
260    
261     if (dirp)
262     g_fileinfo[handle].pdir = dirp;
263     g_fileinfo[handle].device_id = device_id;
264     g_fileinfo[handle].flags_and_attributes = flags_and_attributes;
265     strncpy(g_fileinfo[handle].path, path, 255);
266    
267     *phandle = handle;
268     return STATUS_SUCCESS;
269     }
270    
271     NTSTATUS
272     disk_close(HANDLE handle)
273     {
274     struct fileinfo *pfinfo;
275    
276     pfinfo = &(g_fileinfo[handle]);
277    
278     if (pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE)
279     {
280     closedir(pfinfo->pdir);
281     //FIXME: Should check exit code
282     }
283     else
284     {
285     close(handle);
286     }
287    
288     return STATUS_SUCCESS;
289     }
290    
291     NTSTATUS
292     disk_read(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
293     {
294     int n;
295    
296     if (offset)
297     lseek(handle, offset, SEEK_SET);
298     n = read(handle, data, length);
299    
300     if (n < 0)
301     {
302     perror("read");
303     *result = 0;
304     return STATUS_INVALID_PARAMETER;
305     }
306    
307     *result = n;
308    
309     return STATUS_SUCCESS;
310     }
311    
312     NTSTATUS
313     disk_write(HANDLE handle, uint8 * data, uint32 length, uint32 offset, uint32 * result)
314     {
315     int n;
316    
317     if (offset)
318     lseek(handle, offset, SEEK_SET);
319    
320     n = write(handle, data, length);
321    
322     if (n < 0)
323     {
324     perror("write");
325     *result = 0;
326     return STATUS_ACCESS_DENIED;
327     }
328    
329     *result = n;
330    
331     return STATUS_SUCCESS;
332     }
333    
334     NTSTATUS
335     disk_query_information(HANDLE handle, uint32 info_class, STREAM out)
336     {
337     uint32 file_attributes, ft_high, ft_low;
338     struct stat filestat;
339     char *path, *filename;
340    
341     path = g_fileinfo[handle].path;
342    
343     // Get information about file
344     if (fstat(handle, &filestat) != 0)
345     {
346     perror("stat");
347     out_uint8(out, 0);
348     return STATUS_ACCESS_DENIED;
349     }
350    
351     // Set file attributes
352     file_attributes = 0;
353     if (S_ISDIR(filestat.st_mode))
354     {
355     file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
356     }
357     filename = 1 + strrchr(path, '/');
358     if (filename && filename[0] == '.')
359     {
360     file_attributes |= FILE_ATTRIBUTE_HIDDEN;
361     }
362    
363     // Return requested data
364     switch (info_class)
365     {
366     case 4: /* FileBasicInformation */
367    
368     out_uint8s(out, 8); //create_time not available;
369    
370     seconds_since_1970_to_filetime(filestat.st_atime, &ft_high, &ft_low);
371     out_uint32_le(out, ft_low); //last_access_time
372     out_uint32_le(out, ft_high);
373    
374     seconds_since_1970_to_filetime(filestat.st_mtime, &ft_high, &ft_low);
375     out_uint32_le(out, ft_low); //last_write_time
376     out_uint32_le(out, ft_high);
377    
378     out_uint8s(out, 8); //unknown zero
379     out_uint32_le(out, file_attributes);
380     break;
381    
382     case 5: /* FileStandardInformation */
383    
384     out_uint32_le(out, filestat.st_size); //Allocation size
385     out_uint32_le(out, 0);
386     out_uint32_le(out, filestat.st_size); //End of file
387     out_uint32_le(out, 0);
388     out_uint32_le(out, filestat.st_nlink); //Number of links
389     out_uint8(out, 0); //Delete pending
390     out_uint8(out, S_ISDIR(filestat.st_mode) ? 1 : 0); //Directory
391     break;
392    
393     case 35: /* FileObjectIdInformation */
394    
395     out_uint32_le(out, file_attributes); /* File Attributes */
396     out_uint32_le(out, 0); /* Reparse Tag */
397     break;
398    
399     default:
400    
401     unimpl("IRP Query (File) Information class: 0x%x\n", info_class);
402     return STATUS_INVALID_PARAMETER;
403     }
404     return STATUS_SUCCESS;
405     }
406    
407     NTSTATUS
408     disk_set_information(HANDLE handle, uint32 info_class, STREAM in, STREAM out)
409     {
410     uint32 device_id, length, file_attributes, ft_high, ft_low;
411     char newname[256], fullpath[256];
412     struct fileinfo *pfinfo;
413    
414     pfinfo = &(g_fileinfo[handle]);
415    
416     switch (info_class)
417     {
418     case 4: /* FileBasicInformation */
419    
420     // Probably safe to ignore
421     break;
422    
423     case 10: /* FileRenameInformation */
424    
425     in_uint8s(in, 4); /* Handle of root dir? */
426     in_uint8s(in, 0x1a); /* unknown */
427     in_uint32_le(in, length);
428    
429     if (length && (length / 2) < 256)
430     {
431     rdp_in_unistr(in, newname, length);
432     convert_to_unix_filename(newname);
433     }
434     else
435     {
436     return STATUS_INVALID_PARAMETER;
437     }
438    
439     sprintf(fullpath, "%s%s", g_rdpdr_device[pfinfo->device_id].local_path,
440     newname);
441    
442     if (rename(pfinfo->path, fullpath) != 0)
443     {
444     perror("rename");
445     return STATUS_ACCESS_DENIED;
446     }
447     break;
448    
449     case 13: /* FileDispositionInformation */
450    
451     //unimpl("IRP Set File Information class: FileDispositionInformation\n");
452     // in_uint32_le(in, delete_on_close);
453     // disk_close(handle);
454     unlink(pfinfo->path);
455     break;
456    
457     case 19: /* FileAllocationInformation */
458    
459     unimpl("IRP Set File Information class: FileAllocationInformation\n");
460     break;
461    
462     case 20: /* FileEndOfFileInformation */
463    
464     unimpl("IRP Set File Information class: FileEndOfFileInformation\n");
465     break;
466    
467     default:
468    
469     unimpl("IRP Set File Information class: 0x%x\n", info_class);
470     return STATUS_INVALID_PARAMETER;
471     }
472     return STATUS_SUCCESS;
473     }
474    
475     NTSTATUS
476     disk_query_volume_information(HANDLE handle, uint32 info_class, STREAM out)
477     {
478     char *volume, *fs_type;
479     struct statfs stat_fs;
480     struct fileinfo *pfinfo;
481    
482     pfinfo = &(g_fileinfo[handle]);
483     volume = "RDESKTOP";
484     fs_type = "RDPFS";
485    
486     if (statfs(pfinfo->path, &stat_fs) != 0) /* FIXME: statfs is not portable */
487     {
488     perror("statfs");
489     return STATUS_ACCESS_DENIED;
490     }
491    
492     switch (info_class)
493     {
494     case 1: /* FileFsVolumeInformation */
495    
496     out_uint32_le(out, 0); /* volume creation time low */
497     out_uint32_le(out, 0); /* volume creation time high */
498     out_uint32_le(out, 0); /* serial */
499     out_uint32_le(out, 2 * strlen(volume)); /* length of string */
500     out_uint8(out, 0); /* support objects? */
501     rdp_out_unistr(out, volume, 2 * strlen(volume) - 2);
502     break;
503    
504     case 3: /* FileFsSizeInformation */
505    
506     out_uint32_le(out, stat_fs.f_blocks); /* Total allocation units low */
507     out_uint32_le(out, 0); /* Total allocation high units */
508     out_uint32_le(out, stat_fs.f_bfree); /* Available allocation units */
509     out_uint32_le(out, 0); /* Available allowcation units */
510     out_uint32_le(out, stat_fs.f_bsize / 0x200); /* Sectors per allocation unit */
511     out_uint32_le(out, 0x200); /* Bytes per sector */
512     break;
513    
514     case 5: /* FileFsAttributeInformation */
515    
516     out_uint32_le(out, FS_CASE_SENSITIVE | FS_CASE_IS_PRESERVED); /* fs attributes */
517     out_uint32_le(out, stat_fs.f_namelen); /* max length of filename */
518     out_uint32_le(out, 2 * strlen(fs_type)); /* length of fs_type */
519     rdp_out_unistr(out, fs_type, 2 * strlen(fs_type) - 2);
520     break;
521    
522     case 2: /* FileFsLabelInformation */
523     case 4: /* FileFsDeviceInformation */
524     case 6: /* FileFsControlInformation */
525     case 7: /* FileFsFullSizeInformation */
526     case 8: /* FileFsObjectIdInformation */
527     case 9: /* FileFsMaximumInformation */
528     default:
529    
530     unimpl("IRP Query Volume Information class: 0x%x\n", info_class);
531     return STATUS_INVALID_PARAMETER;
532     }
533     return STATUS_SUCCESS;
534     }
535    
536     NTSTATUS
537     disk_query_directory(HANDLE handle, uint32 info_class, char *pattern, STREAM out)
538     {
539     uint32 file_attributes, ft_low, ft_high;
540     char *dirname, fullpath[256];
541     DIR *pdir;
542     struct dirent *pdirent;
543     struct stat fstat;
544     struct fileinfo *pfinfo;
545    
546     pfinfo = &(g_fileinfo[handle]);
547     pdir = pfinfo->pdir;
548     dirname = pfinfo->path;
549     file_attributes = 0;
550    
551     switch (info_class)
552     {
553     case 3: //FIXME: Why 3?
554    
555     // If a search pattern is received, remember this pattern, and restart search
556     if (pattern[0] != 0)
557     {
558     strncpy(pfinfo->pattern, 1 + strrchr(pattern, '/'), 64);
559     rewinddir(pdir);
560     }
561    
562     // find next dirent matching pattern
563     pdirent = readdir(pdir);
564     while (pdirent && fnmatch(pfinfo->pattern, pdirent->d_name, 0) != 0)
565     {
566     pdirent = readdir(pdir);
567     }
568    
569     if (pdirent == NULL)
570     {
571     return STATUS_NO_MORE_FILES;
572     }
573    
574     // Get information for directory entry
575     sprintf(fullpath, "%s/%s", dirname, pdirent->d_name);
576     /* JIF
577     printf("Stat: %s\n", fullpath); */
578     if (stat(fullpath, &fstat))
579     {
580     perror("stat");
581     out_uint8(out, 0);
582     return STATUS_ACCESS_DENIED;
583     }
584    
585     if (S_ISDIR(fstat.st_mode))
586     file_attributes |= FILE_ATTRIBUTE_DIRECTORY;
587     if (pdirent->d_name[0] == '.')
588     file_attributes |= FILE_ATTRIBUTE_HIDDEN;
589    
590     // Return requested information
591     out_uint8s(out, 8); //unknown zero
592     out_uint8s(out, 8); //create_time not available in posix;
593    
594     seconds_since_1970_to_filetime(fstat.st_atime, &ft_high, &ft_low);
595     out_uint32_le(out, ft_low); //last_access_time
596     out_uint32_le(out, ft_high);
597    
598     seconds_since_1970_to_filetime(fstat.st_mtime, &ft_high, &ft_low);
599     out_uint32_le(out, ft_low); //last_write_time
600     out_uint32_le(out, ft_high);
601    
602     out_uint8s(out, 8); //unknown zero
603     out_uint32_le(out, fstat.st_size); //filesize low
604     out_uint32_le(out, 0); //filesize high
605     out_uint32_le(out, fstat.st_size); //filesize low
606     out_uint32_le(out, 0); //filesize high
607     out_uint32_le(out, file_attributes);
608     out_uint8(out, 2 * strlen(pdirent->d_name) + 2); //unicode length
609     out_uint8s(out, 7); //pad?
610     out_uint8(out, 0); //8.3 file length
611     out_uint8s(out, 2 * 12); //8.3 unicode length
612     rdp_out_unistr(out, pdirent->d_name, 2 * strlen(pdirent->d_name));
613     break;
614    
615     default:
616    
617     unimpl("IRP Query Directory sub: 0x%x\n", info_class);
618     return STATUS_INVALID_PARAMETER;
619     }
620    
621     return STATUS_SUCCESS;
622     }
623    
624     DEVICE_FNS disk_fns = {
625     disk_create,
626     disk_close,
627     disk_read,
628     disk_write,
629     NULL /* device_control */
630     };

  ViewVC Help
Powered by ViewVC 1.1.26