81 |
extern RDPDR_DEVICE g_rdpdr_device[]; |
extern RDPDR_DEVICE g_rdpdr_device[]; |
82 |
|
|
83 |
FILEINFO g_fileinfo[MAX_OPEN_FILES]; |
FILEINFO g_fileinfo[MAX_OPEN_FILES]; |
84 |
|
BOOL g_notify_stamp = False; |
85 |
|
|
86 |
typedef struct |
typedef struct |
87 |
{ |
{ |
91 |
char type[256]; |
char type[256]; |
92 |
} FsInfoType; |
} FsInfoType; |
93 |
|
|
94 |
|
static NTSTATUS NotifyInfo(NTHANDLE handle, uint32 info_class, NOTIFY * p); |
95 |
|
|
96 |
static time_t |
static time_t |
97 |
get_create_time(struct stat *st) |
get_create_time(struct stat *st) |
330 |
break; |
break; |
331 |
} |
} |
332 |
|
|
333 |
//printf("Open: \"%s\" flags: %u, accessmask: %u sharemode: %u create disp: %u\n", path, flags_and_attributes, accessmask, sharemode, create_disposition); |
//printf("Open: \"%s\" flags: %X, accessmask: %X sharemode: %X create disp: %X\n", path, flags_and_attributes, accessmask, sharemode, create_disposition); |
334 |
|
|
335 |
// Get information about file and set that flag ourselfs |
// Get information about file and set that flag ourselfs |
336 |
if ((stat(path, &filestat) == 0) && (S_ISDIR(filestat.st_mode))) |
if ((stat(path, &filestat) == 0) && (S_ISDIR(filestat.st_mode))) |
426 |
|
|
427 |
if (dirp) |
if (dirp) |
428 |
g_fileinfo[handle].pdir = dirp; |
g_fileinfo[handle].pdir = dirp; |
429 |
|
else |
430 |
|
g_fileinfo[handle].pdir = NULL; |
431 |
|
|
432 |
g_fileinfo[handle].device_id = device_id; |
g_fileinfo[handle].device_id = device_id; |
433 |
g_fileinfo[handle].flags_and_attributes = flags_and_attributes; |
g_fileinfo[handle].flags_and_attributes = flags_and_attributes; |
434 |
|
g_fileinfo[handle].accessmask = accessmask; |
435 |
strncpy(g_fileinfo[handle].path, path, 255); |
strncpy(g_fileinfo[handle].path, path, 255); |
436 |
|
g_fileinfo[handle].delete_on_close = False; |
437 |
|
g_notify_stamp = True; |
438 |
|
|
439 |
*phandle = handle; |
*phandle = handle; |
440 |
return STATUS_SUCCESS; |
return STATUS_SUCCESS; |
447 |
|
|
448 |
pfinfo = &(g_fileinfo[handle]); |
pfinfo = &(g_fileinfo[handle]); |
449 |
|
|
450 |
if (pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE) |
g_notify_stamp = True; |
451 |
|
|
452 |
|
rdpdr_abort_io(handle, 0, STATUS_CANCELLED); |
453 |
|
|
454 |
|
if (pfinfo->pdir) |
455 |
{ |
{ |
456 |
closedir(pfinfo->pdir); |
if (closedir(pfinfo->pdir) < 0) |
457 |
//FIXME: Should check exit code |
{ |
458 |
|
perror("closedir"); |
459 |
|
return STATUS_INVALID_HANDLE; |
460 |
|
} |
461 |
|
|
462 |
|
if (pfinfo->delete_on_close) |
463 |
|
if (rmdir(pfinfo->path) < 0) |
464 |
|
{ |
465 |
|
perror(pfinfo->path); |
466 |
|
return STATUS_ACCESS_DENIED; |
467 |
|
} |
468 |
|
pfinfo->delete_on_close = False; |
469 |
} |
} |
470 |
else |
else |
471 |
{ |
{ |
472 |
close(handle); |
if (close(handle) < 0) |
473 |
|
{ |
474 |
|
perror("close"); |
475 |
|
return STATUS_INVALID_HANDLE; |
476 |
|
} |
477 |
|
if (pfinfo->delete_on_close) |
478 |
|
if (unlink(pfinfo->path) < 0) |
479 |
|
{ |
480 |
|
perror(pfinfo->path); |
481 |
|
return STATUS_ACCESS_DENIED; |
482 |
|
} |
483 |
|
|
484 |
|
pfinfo->delete_on_close = False; |
485 |
} |
} |
486 |
|
|
487 |
return STATUS_SUCCESS; |
return STATUS_SUCCESS; |
512 |
switch (errno) |
switch (errno) |
513 |
{ |
{ |
514 |
case EISDIR: |
case EISDIR: |
515 |
return STATUS_FILE_IS_A_DIRECTORY; |
/* Implement 24 Byte directory read ?? |
516 |
|
with STATUS_NOT_IMPLEMENTED server doesn't read again */ |
517 |
|
/* return STATUS_FILE_IS_A_DIRECTORY; */ |
518 |
|
return STATUS_NOT_IMPLEMENTED; |
519 |
default: |
default: |
520 |
perror("read"); |
perror("read"); |
521 |
return STATUS_INVALID_PARAMETER; |
return STATUS_INVALID_PARAMETER; |
638 |
NTSTATUS |
NTSTATUS |
639 |
disk_set_information(NTHANDLE handle, uint32 info_class, STREAM in, STREAM out) |
disk_set_information(NTHANDLE handle, uint32 info_class, STREAM in, STREAM out) |
640 |
{ |
{ |
641 |
uint32 length, file_attributes, ft_high, ft_low; |
uint32 length, file_attributes, ft_high, ft_low, delete_on_close; |
642 |
char newname[256], fullpath[256]; |
char newname[256], fullpath[256]; |
643 |
struct fileinfo *pfinfo; |
struct fileinfo *pfinfo; |
|
|
|
644 |
int mode; |
int mode; |
645 |
struct stat filestat; |
struct stat filestat; |
646 |
time_t write_time, change_time, access_time, mod_time; |
time_t write_time, change_time, access_time, mod_time; |
648 |
struct STATFS_T stat_fs; |
struct STATFS_T stat_fs; |
649 |
|
|
650 |
pfinfo = &(g_fileinfo[handle]); |
pfinfo = &(g_fileinfo[handle]); |
651 |
|
g_notify_stamp = True; |
652 |
|
|
653 |
switch (info_class) |
switch (info_class) |
654 |
{ |
{ |
708 |
printf("FileBasicInformation modification time %s", |
printf("FileBasicInformation modification time %s", |
709 |
ctime(&tvs.modtime)); |
ctime(&tvs.modtime)); |
710 |
#endif |
#endif |
711 |
if (utime(pfinfo->path, &tvs)) |
if (utime(pfinfo->path, &tvs) && errno != EPERM) |
712 |
return STATUS_ACCESS_DENIED; |
return STATUS_ACCESS_DENIED; |
713 |
} |
} |
714 |
|
|
766 |
FileDispositionInformation requests with |
FileDispositionInformation requests with |
767 |
DeleteFile set to FALSE should unschedule |
DeleteFile set to FALSE should unschedule |
768 |
the delete. See |
the delete. See |
769 |
http://www.osronline.com/article.cfm?article=245. Currently, |
http://www.osronline.com/article.cfm?article=245. */ |
|
we are deleting the file immediately. I |
|
|
guess this is a FIXME. */ |
|
770 |
|
|
771 |
//in_uint32_le(in, delete_on_close); |
in_uint32_le(in, delete_on_close); |
772 |
|
|
773 |
/* Make sure we close the file before |
if (delete_on_close || |
774 |
unlinking it. Not doing so would trigger |
(pfinfo-> |
775 |
silly-delete if using NFS, which might fail |
accessmask & (FILE_DELETE_ON_CLOSE | FILE_COMPLETE_IF_OPLOCKED))) |
|
on FAT floppies, for example. */ |
|
|
disk_close(handle); |
|
|
|
|
|
if ((pfinfo->flags_and_attributes & FILE_DIRECTORY_FILE)) // remove a directory |
|
776 |
{ |
{ |
777 |
if (rmdir(pfinfo->path) < 0) |
pfinfo->delete_on_close = True; |
|
return STATUS_ACCESS_DENIED; |
|
778 |
} |
} |
|
else if (unlink(pfinfo->path) < 0) // unlink a file |
|
|
return STATUS_ACCESS_DENIED; |
|
779 |
|
|
780 |
break; |
break; |
781 |
|
|
792 |
|
|
793 |
/* prevents start of writing if not enough space left on device */ |
/* prevents start of writing if not enough space left on device */ |
794 |
if (STATFS_FN(g_rdpdr_device[pfinfo->device_id].local_path, &stat_fs) == 0) |
if (STATFS_FN(g_rdpdr_device[pfinfo->device_id].local_path, &stat_fs) == 0) |
795 |
if (stat_fs.f_bsize * stat_fs.f_bfree < length) |
if (stat_fs.f_bfree * stat_fs.f_bsize < length) |
796 |
return STATUS_DISK_FULL; |
return STATUS_DISK_FULL; |
797 |
|
|
798 |
if (ftruncate_growable(handle, length) != 0) |
if (ftruncate_growable(handle, length) != 0) |
809 |
return STATUS_SUCCESS; |
return STATUS_SUCCESS; |
810 |
} |
} |
811 |
|
|
812 |
|
NTSTATUS |
813 |
|
disk_check_notify(NTHANDLE handle) |
814 |
|
{ |
815 |
|
struct fileinfo *pfinfo; |
816 |
|
NTSTATUS status = STATUS_PENDING; |
817 |
|
|
818 |
|
NOTIFY notify; |
819 |
|
|
820 |
|
pfinfo = &(g_fileinfo[handle]); |
821 |
|
if (!pfinfo->pdir) |
822 |
|
return STATUS_INVALID_DEVICE_REQUEST; |
823 |
|
|
824 |
|
|
825 |
|
|
826 |
|
status = NotifyInfo(handle, pfinfo->info_class, ¬ify); |
827 |
|
|
828 |
|
if (status != STATUS_PENDING) |
829 |
|
return status; |
830 |
|
|
831 |
|
if (memcmp(&pfinfo->notify, ¬ify, sizeof(NOTIFY))) |
832 |
|
{ |
833 |
|
//printf("disk_check_notify found changed event\n"); |
834 |
|
memcpy(&pfinfo->notify, ¬ify, sizeof(NOTIFY)); |
835 |
|
status = STATUS_NOTIFY_ENUM_DIR; |
836 |
|
} |
837 |
|
|
838 |
|
return status; |
839 |
|
|
840 |
|
|
841 |
|
} |
842 |
|
|
843 |
|
NTSTATUS |
844 |
|
disk_create_notify(NTHANDLE handle, uint32 info_class) |
845 |
|
{ |
846 |
|
|
847 |
|
struct fileinfo *pfinfo; |
848 |
|
NTSTATUS ret = STATUS_PENDING; |
849 |
|
|
850 |
|
/* printf("start disk_create_notify info_class %X\n", info_class); */ |
851 |
|
|
852 |
|
pfinfo = &(g_fileinfo[handle]); |
853 |
|
pfinfo->info_class = info_class; |
854 |
|
|
855 |
|
ret = NotifyInfo(handle, info_class, &pfinfo->notify); |
856 |
|
|
857 |
|
if (info_class & 0x1000) |
858 |
|
{ /* ???? */ |
859 |
|
if (ret == STATUS_PENDING) |
860 |
|
return STATUS_SUCCESS; |
861 |
|
} |
862 |
|
|
863 |
|
/* printf("disk_create_notify: num_entries %d\n", pfinfo->notify.num_entries); */ |
864 |
|
|
865 |
|
|
866 |
|
return ret; |
867 |
|
|
868 |
|
} |
869 |
|
|
870 |
|
static NTSTATUS |
871 |
|
NotifyInfo(NTHANDLE handle, uint32 info_class, NOTIFY * p) |
872 |
|
{ |
873 |
|
struct fileinfo *pfinfo; |
874 |
|
struct stat buf; |
875 |
|
struct dirent *dp; |
876 |
|
char *fullname; |
877 |
|
DIR *dpr; |
878 |
|
|
879 |
|
pfinfo = &(g_fileinfo[handle]); |
880 |
|
if (fstat(handle, &buf) < 0) |
881 |
|
{ |
882 |
|
perror("NotifyInfo"); |
883 |
|
return STATUS_ACCESS_DENIED; |
884 |
|
} |
885 |
|
p->modify_time = buf.st_mtime; |
886 |
|
p->status_time = buf.st_ctime; |
887 |
|
p->num_entries = 0; |
888 |
|
p->total_time = 0; |
889 |
|
|
890 |
|
|
891 |
|
dpr = opendir(pfinfo->path); |
892 |
|
if (!dpr) |
893 |
|
{ |
894 |
|
perror("NotifyInfo"); |
895 |
|
return STATUS_ACCESS_DENIED; |
896 |
|
} |
897 |
|
|
898 |
|
|
899 |
|
while ((dp = readdir(dpr))) |
900 |
|
{ |
901 |
|
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) |
902 |
|
continue; |
903 |
|
p->num_entries++; |
904 |
|
fullname = xmalloc(strlen(pfinfo->path) + strlen(dp->d_name) + 2); |
905 |
|
sprintf(fullname, "%s/%s", pfinfo->path, dp->d_name); |
906 |
|
|
907 |
|
if (!stat(fullname, &buf)) |
908 |
|
{ |
909 |
|
p->total_time += (buf.st_mtime + buf.st_ctime); |
910 |
|
} |
911 |
|
|
912 |
|
xfree(fullname); |
913 |
|
} |
914 |
|
closedir(dpr); |
915 |
|
|
916 |
|
return STATUS_PENDING; |
917 |
|
} |
918 |
|
|
919 |
static FsInfoType * |
static FsInfoType * |
920 |
FsVolumeInfo(char *fpath) |
FsVolumeInfo(char *fpath) |
921 |
{ |
{ |
922 |
|
|
|
#ifdef HAVE_MNTENT_H |
|
923 |
FILE *fdfs; |
FILE *fdfs; |
|
struct mntent *e; |
|
924 |
static FsInfoType info; |
static FsInfoType info; |
925 |
|
#ifdef HAVE_MNTENT_H |
926 |
|
struct mntent *e; |
927 |
|
#endif |
928 |
|
|
929 |
/* initialize */ |
/* initialize */ |
930 |
memset(&info, 0, sizeof(info)); |
memset(&info, 0, sizeof(info)); |
931 |
strcpy(info.label, "RDESKTOP"); |
strcpy(info.label, "RDESKTOP"); |
932 |
strcpy(info.type, "RDPFS"); |
strcpy(info.type, "RDPFS"); |
933 |
|
|
934 |
|
#ifdef HAVE_MNTENT_H |
935 |
fdfs = setmntent(MNTENT_PATH, "r"); |
fdfs = setmntent(MNTENT_PATH, "r"); |
936 |
if (!fdfs) |
if (!fdfs) |
937 |
return &info; |
return &info; |
974 |
} |
} |
975 |
endmntent(fdfs); |
endmntent(fdfs); |
976 |
#else |
#else |
|
static FsInfoType info; |
|
|
|
|
977 |
/* initialize */ |
/* initialize */ |
978 |
memset(&info, 0, sizeof(info)); |
memset(&info, 0, sizeof(info)); |
979 |
strcpy(info.label, "RDESKTOP"); |
strcpy(info.label, "RDESKTOP"); |