The attached patch fixes multiple issues with writeBckVersion():
- Use correct types (size_t+ssize_t versus int)
- Removed very odd casts
- Don't read+write whole file in one go as the doubles memory requirements
for large files.
- Fix file permissions on backup file.
- IBM_FWRITE_BUG workaround removed because it is not special anymore.
WriteBackupFile() probably needs same treatment, but I am not sure if VMS
supports file-descriptor-based I/O.
--- nedit.isj5/source/file.c 2007-10-08 22:22:59.000000000 +0200
+++ nedit.isj6/source/file.c 2007-10-14 13:52:50.000000000 +0200
@@ -1180,13 +1180,13 @@
#ifndef VMS
char fullname[MAXPATHLEN], bckname[MAXPATHLEN];
struct stat statbuf;
- FILE *inFP, *outFP;
- int fd, fileLen;
- char *fileString;
+ int in_fd, out_fd;
+ char *io_buffer;
+#define IO_BUFFER_SIZE ((size_t)(1024*1024))
/* Do only if version backups are turned on */
if (!window->saveOldVersion) {
- return False;
+ return FALSE;
}
/* Get the full name of the file */
@@ -1194,7 +1194,7 @@
strcat(fullname, window->filename);
/* Generate name for old version */
- if ((int)(strlen(fullname) + 5) > (int)MAXPATHLEN)
+ if ((strlen(fullname) + 5) > (size_t)MAXPATHLEN)
{
return bckError(window, "file name too long", window->filename);
}
@@ -1202,65 +1202,76 @@
/* Delete the old backup file */
/* Errors are ignored; we'll notice them later. */
- unlink(bckname);
+ remove(bckname);
/* open the file being edited. If there are problems with the
old file, don't bother the user, just skip the backup */
- inFP = fopen(fullname, "rb");
- if (inFP == NULL) {
+ in_fd = open(fullname, O_RDONLY);
+ if (in_fd<0) {
return FALSE;
}
- /* find the length of the file */
- if (fstat(fileno(inFP), &statbuf) != 0) {
+ /* Get permissions of the file.
+ We preserve the normal permissions but not ownership, extended
+ attributes, et cetera. */
+ if (fstat(in_fd, &statbuf) != 0) {
return FALSE;
}
- fileLen = statbuf.st_size;
- /* open the file exclusive and with restrictive permissions. */
- if ((fd = open(bckname, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR | S_IWUSR)) < 0
- || (outFP = fdopen(fd, "wb")) == NULL) {
- fclose(inFP);
+ /* open the destination file exclusive and with restrictive permissions. */
+ out_fd = open(bckname, O_CREAT|O_EXCL|O_TRUNC|O_WRONLY, S_IRUSR | S_IWUSR);
+ if (out_fd < 0) {
return bckError(window, "Error open backup file", bckname);
}
-
- /* Allocate space for the whole contents of the file */
- fileString = (char *)malloc(fileLen);
- if (fileString == NULL) {
- fclose(inFP);
- fclose(outFP);
+
+ /* Set permissions on new file */
+ if (fchmod(out_fd, statbuf.st_mode) != 0) {
+ close(in_fd);
+ close(out_fd);
+ remove(bckname);
+ return bckError(window, "fchmod() failed", bckname);
+ }
+
+ /* Allocate I/O buffer */
+ io_buffer = (char *)malloc(IO_BUFFER_SIZE);
+ if (io_buffer == NULL) {
+ close(in_fd);
+ close(out_fd);
+ remove(bckname);
return bckError(window, "out of memory", bckname);
}
-
- /* read the file into fileString */
- fread(fileString, sizeof(char), fileLen, inFP);
- if (ferror(inFP)) {
- fclose(inFP);
- fclose(outFP);
- free(fileString);
- return FALSE;
+
+ /* copy loop */
+ for(;;) {
+ ssize_t bytes_read;
+ ssize_t bytes_written;
+ bytes_read = read(in_fd, io_buffer, IO_BUFFER_SIZE);
+ if (bytes_read<0) {
+ close(in_fd);
+ close(out_fd);
+ remove(bckname);
+ free(io_buffer);
+ return bckError(window, "read() error", window->filename);
+ }
+ if (bytes_read==0)
+ break; /* EOF */
+ /* write to the file */
+ bytes_written = write(out_fd, io_buffer, (size_t)bytes_read);
+ if (bytes_written!=bytes_read) {
+ close(in_fd);
+ close(out_fd);
+ remove(bckname);
+ free(io_buffer);
+ return bckError(window, errorString(), bckname);
+ }
}
-
- /* close the input file, ignore any errors */
- fclose(inFP);
- /* write to the file */
-#ifdef IBM_FWRITE_BUG
- write(fileno(outFP), fileString, fileLen);
-#else
- fwrite(fileString, sizeof(char), fileLen, outFP);
-#endif
- if (ferror(outFP)) {
- fclose(outFP);
- remove(bckname);
- free(fileString);
- return bckError(window, errorString(), bckname);
- }
- free(fileString);
-
- /* close the file */
- if (fclose(outFP) != 0)
- return bckError(window, errorString(), bckname);
+ /* close the input and output files */
+ close(in_fd);
+ close(out_fd);
+
+ free(io_buffer);
+
#endif /* VMS */
return FALSE;
--
NEdit Develop mailing list - [email protected]
http://www.nedit.org/mailman/listinfo/develop