--- sourceforge.net/trunk/rdesktop/disk.c 2004/10/02 01:30:33 776 +++ sourceforge.net/trunk/rdesktop/disk.c 2004/10/21 08:28:03 787 @@ -52,7 +52,7 @@ #define STATFS_T statvfs #define F_NAMELEN(buf) ((buf).f_namemax) -#elif (defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)) +#elif (defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__APPLE__)) #include #include #define STATFS_FN(path, buf) (statfs(path,buf)) @@ -132,6 +132,65 @@ } +/* A wrapper for ftruncate which supports growing files, even if the + native ftruncate doesn't. This is needed on Linux FAT filesystems, + for example. */ +static int +ftruncate_growable(int fd, off_t length) +{ + int ret; + off_t pos; + static const char zero; + + /* Try the simple method first */ + if ((ret = ftruncate(fd, length)) != -1) + { + return ret; + } + + /* + * Some kind of error. Perhaps we were trying to grow. Retry + * in a safe way. + */ + + /* Get current position */ + if ((pos = lseek(fd, 0, SEEK_CUR)) == -1) + { + perror("lseek"); + return -1; + } + + /* Seek to new size */ + if (lseek(fd, length, SEEK_SET) == -1) + { + perror("lseek"); + return -1; + } + + /* Write a zero */ + if (write(fd, &zero, 1) == -1) + { + perror("write"); + return -1; + } + + /* Truncate. This shouldn't fail. */ + if (ftruncate(fd, length) == -1) + { + perror("ftruncate"); + return -1; + } + + /* Restore position */ + if (lseek(fd, pos, SEEK_SET) == -1) + { + perror("lseek"); + return -1; + } + + return 0; +} + /* Enumeration of devices from rdesktop.c */ /* returns numer of units found and initialized. */ @@ -182,8 +241,7 @@ flags = 0; mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH; - - if (filename[strlen(filename) - 1] == '/') + if (*filename && filename[strlen(filename) - 1] == '/') filename[strlen(filename) - 1] = 0; sprintf(path, "%s%s", g_rdpdr_device[device_id].local_path, filename); @@ -492,7 +550,7 @@ NTSTATUS disk_set_information(NTHANDLE handle, uint32 info_class, STREAM in, STREAM out) { - uint32 device_id, length, file_attributes, ft_high, ft_low; + uint32 length, file_attributes, ft_high, ft_low; char newname[256], fullpath[256]; struct fileinfo *pfinfo; @@ -658,11 +716,8 @@ if (stat_fs.f_bsize * stat_fs.f_bfree < length) return STATUS_DISK_FULL; - /* FIXME: Growing file with ftruncate doesn't - work with Linux FAT fs */ - if (ftruncate(handle, length) != 0) + if (ftruncate_growable(handle, length) != 0) { - perror("ftruncate"); return STATUS_DISK_FULL; } @@ -921,8 +976,6 @@ static NTSTATUS disk_device_control(NTHANDLE handle, uint32 request, STREAM in, STREAM out) { - uint32 result; - if (((request >> 16) != 20) || ((request >> 16) != 9)) return STATUS_INVALID_PARAMETER;