--- sourceforge.net/trunk/rdesktop/disk.c 2004/01/21 22:13:20 573 +++ sourceforge.net/trunk/rdesktop/disk.c 2004/02/03 14:03:42 596 @@ -84,18 +84,21 @@ #if defined(SOLARIS) #include /* solaris statvfs */ -#define HAVE_STATVFS +#define STATFS_FN(path, buf) (statvfs(path,buf)) +#define STATFS_T statvfs #define F_NAMELEN(buf) ((buf).f_namemax) -#elif defined(__OpenBSD__) +#elif (defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)) #include #include -#define HAVE_STATFS +#define STATFS_FN(path, buf) (statfs(path,buf)) +#define STATFS_T statfs #define F_NAMELEN(buf) (NAME_MAX) #else #include /* linux statfs */ -#define HAVE_STATFS +#define STATFS_FN(path, buf) (statfs(path,buf)) +#define STATFS_T statfs #define F_NAMELEN(buf) ((buf).f_namelen) #endif @@ -114,11 +117,6 @@ } g_fileinfo[MAX_OPEN_FILES]; -struct fsinfo -{ - uint32 f_blocks, f_bfree, f_bsize, f_namelen; -}; - /* Convert seconds since 1970 to a filetime */ void seconds_since_1970_to_filetime(time_t seconds, uint32 * high, uint32 * low) @@ -165,7 +163,7 @@ return count; } -/* Opens of creates a file or directory */ +/* Opens or creates a file or directory */ NTSTATUS disk_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create_disposition, uint32 flags_and_attributes, char *filename, HANDLE * phandle) @@ -183,7 +181,6 @@ if (filename[strlen(filename) - 1] == '/') filename[strlen(filename) - 1] = 0; sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename); - //printf("Open: %s\n", path); switch (create_disposition) { @@ -218,15 +215,26 @@ break; } - if (flags_and_attributes & FILE_DIRECTORY_FILE) + /* the sad part is that we can't trust this flag */ + /* directories aren't always marked */ + if (flags_and_attributes ^ FILE_DIRECTORY_FILE) { - if (flags & O_CREAT) + if (accessmask & GENERIC_ALL + || (accessmask & GENERIC_READ && accessmask & GENERIC_WRITE)) { - mkdir(path, mode); + flags |= O_RDWR; + } + else if ((accessmask & GENERIC_WRITE) && !(accessmask & GENERIC_READ)) + { + flags |= O_WRONLY; + } + else + { + flags |= O_RDONLY; } - dirp = opendir(path); - if (!dirp) + handle = open(path, flags, mode); + if (handle == -1) { switch (errno) { @@ -240,30 +248,42 @@ default: - perror("opendir"); + perror("open"); return STATUS_NO_SUCH_FILE; } } - handle = DIRFD(dirp); + + /* all read and writes of files should be non blocking */ + if (fcntl(handle, F_SETFL, O_NONBLOCK) == -1) + perror("fcntl"); } - else + + /* since we can't trust the FILE_DIRECTORY_FILE flag */ + /* we need to double check that the file isn't a dir */ + if (handle != 0) { - if (accessmask & GENERIC_ALL - || (accessmask & GENERIC_READ && accessmask & GENERIC_WRITE)) - { - flags |= O_RDWR; - } - else if ((accessmask & GENERIC_WRITE) && !(accessmask & GENERIC_READ)) + /* Must check if this file isn't actually a directory */ + struct stat filestat; + + // Get information about file and set that flag ourselfs + if ((fstat(handle, &filestat) == 0) && (S_ISDIR(filestat.st_mode))) { - flags |= O_WRONLY; + flags_and_attributes |= FILE_DIRECTORY_FILE; + close(handle); + handle = 0; } - else + } + + + if (flags_and_attributes & FILE_DIRECTORY_FILE) + { + if (flags & O_CREAT) { - flags |= O_RDONLY; + mkdir(path, mode); } - handle = open(path, flags, mode); - if (handle == -1) + dirp = opendir(path); + if (!dirp) { switch (errno) { @@ -277,10 +297,11 @@ default: - perror("open"); + perror("opendir"); return STATUS_NO_SUCH_FILE; } } + handle = DIRFD(dirp); } if (handle >= MAX_OPEN_FILES) @@ -294,6 +315,7 @@ g_fileinfo[handle].pdir = dirp; g_fileinfo[handle].device_id = device_id; g_fileinfo[handle].flags_and_attributes = flags_and_attributes; +// printf("create: attrib: %u handle %u\n", g_fileinfo[handle].flags_and_attributes, handle ); strncpy(g_fileinfo[handle].path, path, 255); *phandle = handle; @@ -325,6 +347,14 @@ { int n; + /* browsing dir ???? */ + /* each request is 24 bytes */ + if (g_fileinfo[handle].flags_and_attributes & FILE_DIRECTORY_FILE) + { + *result = 0; + return STATUS_SUCCESS; + } + if (offset) lseek(handle, offset, SEEK_SET); n = read(handle, data, length); @@ -504,43 +534,18 @@ return STATUS_SUCCESS; } -int fsstat(const char *path, struct fsinfo *buf) -{ - int ret; -#if defined(HAVE_STATFS) - struct statfs statbuf; -#elif defined(HAVE_STATVFS) - struct statvfs statbuf; -#endif - -#if defined(HAVE_STATFS) - ret = statfs(path, &statbuf); -#elif defined(HAVE_STATVFS) - ret = statvfs(path, &statbuf); -#else - ret=-1; -#endif - - buf->f_blocks = statbuf.f_blocks; - buf->f_bfree = statbuf.f_bfree; - buf->f_bsize = statbuf.f_bsize; - buf->f_namelen = F_NAMELEN(statbuf); - - return ret; -} - NTSTATUS disk_query_volume_information(HANDLE handle, uint32 info_class, STREAM out) { char *volume, *fs_type; - struct fsinfo stat_fs; + struct STATFS_T stat_fs; struct fileinfo *pfinfo; pfinfo = &(g_fileinfo[handle]); volume = "RDESKTOP"; fs_type = "RDPFS"; - if (fsstat(pfinfo->path, &stat_fs) != 0) /* FIXME: statfs is not portable */ + if (STATFS_FN(pfinfo->path, &stat_fs) != 0) /* FIXME: statfs is not portable */ { perror("statfs"); return STATUS_ACCESS_DENIED; @@ -571,7 +576,7 @@ case 5: /* FileFsAttributeInformation */ out_uint32_le(out, FS_CASE_SENSITIVE | FS_CASE_IS_PRESERVED); /* fs attributes */ - out_uint32_le(out, stat_fs.f_namelen); /* max length of filename */ + out_uint32_le(out, F_NAMELEN(stat_fs)); /* max length of filename */ out_uint32_le(out, 2 * strlen(fs_type)); /* length of fs_type */ rdp_out_unistr(out, fs_type, 2 * strlen(fs_type) - 2); break; @@ -630,7 +635,7 @@ // Get information for directory entry sprintf(fullpath, "%s/%s", dirname, pdirent->d_name); - /* JIF + /* JIF printf("Stat: %s\n", fullpath); */ if (stat(fullpath, &fstat)) {