/[rdesktop]/jpeg/rdesktop/trunk/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

Contents of /jpeg/rdesktop/trunk/disk.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 572 - (show annotations)
Wed Jan 21 21:51:59 2004 UTC (20 years, 4 months ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/disk.c
File MIME type: text/plain
File size: 16049 byte(s)
rdesktop compiles again on solaris

1 /* -*- 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 #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 #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
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 #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 struct fsinfo
109 {
110 uint32 f_blocks, f_bfree, f_bsize, f_namelen;
111 };
112
113 /* 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 toupper_str(g_rdpdr_device[*id].name);
143
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 handle = DIRFD(dirp);
239 }
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 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 NTSTATUS
525 disk_query_volume_information(HANDLE handle, uint32 info_class, STREAM out)
526 {
527 char *volume, *fs_type;
528 struct fsinfo stat_fs;
529 struct fileinfo *pfinfo;
530
531 pfinfo = &(g_fileinfo[handle]);
532 volume = "RDESKTOP";
533 fs_type = "RDPFS";
534
535 if (fsstat(pfinfo->path, &stat_fs) != 0) /* FIXME: statfs is not portable */
536 {
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