/[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 572 - (hide annotations)
Wed Jan 21 21:51:59 2004 UTC (20 years, 4 months ago) by stargo
File MIME type: text/plain
File size: 16049 byte(s)
rdesktop compiles again on solaris

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

  ViewVC Help
Powered by ViewVC 1.1.26