Fix removing temporary file after editing in (Disp)VM
Fix removing the file - do not free its filename just before unlink call (scheduled with atexit function). At the same time, place the temporary file in a unique directory, making it possible to edit multiple files with the same name at once. Remove that directory at exit too. Fixes QubesOS/qubes-issues#3112
This commit is contained in:
		
							parent
							
								
									2068299126
								
							
						
					
					
						commit
						e2789ca2d7
					
				| @ -15,6 +15,7 @@ | ||||
| // #define DEBUG
 | ||||
| 
 | ||||
| static const char *cleanup_filename = NULL; | ||||
| static const char *cleanup_dirname = NULL; | ||||
| 
 | ||||
| static void cleanup_file(void) | ||||
| { | ||||
| @ -23,6 +24,11 @@ static void cleanup_file(void) | ||||
| 			fprintf(stderr, "Failed to remove file at exit\n"); | ||||
| 		cleanup_filename = NULL; | ||||
| 	} | ||||
| 	if (cleanup_dirname) { | ||||
| 		if (rmdir(cleanup_dirname) < 0) | ||||
| 			fprintf(stderr, "Failed to remove directory at exit\n"); | ||||
| 		cleanup_dirname = NULL; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| const char *gettime(void) | ||||
| @ -40,8 +46,7 @@ static char *get_directory(void) | ||||
| 	const char *remote_domain; | ||||
| 	char *dir; | ||||
| 	size_t len; | ||||
| 	struct stat dstat; | ||||
| 	int ret; | ||||
| 	char *ret; | ||||
| 
 | ||||
| 	remote_domain = getenv("QREXEC_REMOTE_DOMAIN"); | ||||
| 	if (!remote_domain) { | ||||
| @ -53,29 +58,21 @@ static char *get_directory(void) | ||||
| 	if (!strcmp(remote_domain, ".") || !strcmp(remote_domain, "..")) | ||||
| 		goto fail; | ||||
| 
 | ||||
| 	len = strlen("/tmp")+1+strlen(remote_domain)+1; | ||||
| 	len = strlen("/tmp/-XXXXXX")+strlen(remote_domain)+1; | ||||
| 	dir = malloc(len); | ||||
| 	if (!dir) { | ||||
| 		fprintf(stderr, "Cannot allocate memory\n"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	snprintf(dir, len, "/tmp/%s", remote_domain); | ||||
| 	snprintf(dir, len, "/tmp/%s-XXXXXX", remote_domain); | ||||
| 
 | ||||
| 	ret=mkdir(dir, 0777); | ||||
| 	if (ret<0 && errno!=EEXIST) { | ||||
| 		perror("mkdir"); | ||||
| 	ret = mkdtemp(dir); | ||||
| 	if (ret == NULL) { | ||||
| 		perror("mkdtemp"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	if (stat(dir, &dstat)) { | ||||
| 		perror("stat dir"); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	if (!S_ISDIR(dstat.st_mode)) { | ||||
| 		fprintf(stderr, "%s exists and is not a directory\n", dir); | ||||
| 		exit(1); | ||||
| 	} | ||||
| 
 | ||||
| 	return dir; | ||||
| 	cleanup_dirname = strdup(ret); | ||||
| 	return ret; | ||||
| 
 | ||||
| fail: | ||||
| 	fprintf(stderr, "Invalid remote domain name: %s\n", remote_domain); | ||||
| @ -122,7 +119,7 @@ void copy_file_by_name(const char *filename) | ||||
| 		exit(1); | ||||
| 	} | ||||
| 	/* we now have created a new file, ensure we delete it at the end */ | ||||
| 	cleanup_filename = filename; | ||||
| 	cleanup_filename = strdup(filename); | ||||
| 	atexit(cleanup_file); | ||||
| 	if (!copy_fd_all(fd, 0)) | ||||
|         exit(1); | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Marek Marczykowski-Górecki
						Marek Marczykowski-Górecki