/[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 570 - (show annotations)
Wed Jan 21 18:02:38 2004 UTC (20 years, 4 months ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/disk.c
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 /* -*- 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 toupper_str(g_rdpdr_device[*id].name);
120
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 handle = dirfd(dirp); /* FIXME: dirfd is not portable */
216 }
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