From 636736861688abe73cc5dd4181fdb66de3fd8cfd Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 18 Aug 2015 16:17:30 -0700 Subject: [PATCH] Fix file name encodings in diagnostics Also, close some minor races when opening image files, by opening them once instead of multiple times. * src/gtkutil.c (xg_get_image_for_pixmap): * src/image.c (xpm_load, tiff_load, gif_load, imagemagick_load) (svg_load): * src/nsimage.m (allocInitFromFile:): * src/xfns.c (xg_set_icon): Encode file name, since x_find_image_file no longer does that. * src/image.c (x_find_image_fd): New function. (x_find_image_file): Use it. Do not encode resulting file name, since callers sometimes need it decoded. (slurp_file): File arg is now a fd, not a file name. All callers changed. This saves us having to open the file twice. (xbm_load, xpm_load, pbm_load, png_load_body, jpeg_load_body) (svg_load): Use x_find_image_fd and fdopen to save a file-open. Report file name that failed. * src/lread.c (openp): If PREDICATE is t, open the file in binary mode. --- src/gtkutil.c | 5 +- src/image.c | 133 +++++++++++++++++++++++++++----------------------- src/lread.c | 13 +++-- src/nsimage.m | 1 + src/xfns.c | 2 +- 5 files changed, 84 insertions(+), 70 deletions(-) diff --git a/src/gtkutil.c b/src/gtkutil.c index a4b4331c039..d684cd90888 100644 --- a/src/gtkutil.c +++ b/src/gtkutil.c @@ -382,10 +382,11 @@ xg_get_image_for_pixmap (struct frame *f, if (STRINGP (specified_file) && STRINGP (file = x_find_image_file (specified_file))) { + char *encoded_file = SSDATA (ENCODE_FILE (file)); if (! old_widget) - old_widget = GTK_IMAGE (gtk_image_new_from_file (SSDATA (file))); + old_widget = GTK_IMAGE (gtk_image_new_from_file (encoded_file)); else - gtk_image_set_from_file (old_widget, SSDATA (file)); + gtk_image_set_from_file (old_widget, encoded_file); return GTK_WIDGET (old_widget); } diff --git a/src/image.c b/src/image.c index fb8c6e79168..8f9b06cc284 100644 --- a/src/image.c +++ b/src/image.c @@ -2270,11 +2270,13 @@ image_unget_x_image (struct image *img, bool mask_p, XImagePtr ximg) ***********************************************************************/ /* Find image file FILE. Look in data-directory/images, then - x-bitmap-file-path. Value is the encoded full name of the file - found, or nil if not found. */ + x-bitmap-file-path. Value is the full name of the file + found, or nil if not found. If PFD is nonnull store into *PFD a + readable file descriptor for the file, opened in binary mode. If + PFD is null, do not open the file. */ -Lisp_Object -x_find_image_file (Lisp_Object file) +static Lisp_Object +x_find_image_fd (Lisp_Object file, int *pfd) { Lisp_Object file_found, search_path; int fd; @@ -2286,29 +2288,35 @@ x_find_image_file (Lisp_Object file) Vx_bitmap_file_path); /* Try to find FILE in data-directory/images, then x-bitmap-file-path. */ - fd = openp (search_path, file, Qnil, &file_found, Qnil, false); - - if (fd == -1) - file_found = Qnil; - else - { - file_found = ENCODE_FILE (file_found); - if (fd != -2) - emacs_close (fd); - } - + fd = openp (search_path, file, Qnil, &file_found, + pfd ? Qt : make_number (R_OK), false); + if (fd < 0) + return Qnil; + if (pfd) + *pfd = fd; return file_found; } +/* Find image file FILE. Look in data-directory/images, then + x-bitmap-file-path. Value is the encoded full name of the file + found, or nil if not found. */ + +Lisp_Object +x_find_image_file (Lisp_Object file) +{ + return x_find_image_fd (file, 0); +} /* Read FILE into memory. Value is a pointer to a buffer allocated with xmalloc holding FILE's contents. Value is null if an error - occurred. *SIZE is set to the size of the file. */ + occurred. FD is a file descriptor open for reading FILE. Set + *SIZE to the size of the file. */ static unsigned char * -slurp_file (char *file, ptrdiff_t *size) +slurp_file (int fd, ptrdiff_t *size) { - FILE *fp = emacs_fopen (file, "rb"); + FILE *fp = fdopen (fd, "rb"); + unsigned char *buf = NULL; struct stat st; @@ -2980,21 +2988,19 @@ xbm_load (struct frame *f, struct image *img) file_name = image_spec_value (img->spec, QCfile, NULL); if (STRINGP (file_name)) { - Lisp_Object file; - unsigned char *contents; - ptrdiff_t size; - - file = x_find_image_file (file_name); + int fd; + Lisp_Object file = x_find_image_fd (file_name, &fd); if (!STRINGP (file)) { image_error ("Cannot find image file "uLSQM"%s"uRSQM, file_name); return 0; } - contents = slurp_file (SSDATA (file), &size); + ptrdiff_t size; + unsigned char *contents = slurp_file (fd, &size); if (contents == NULL) { - image_error ("Error loading XBM image "uLSQM"%s"uRSQM, img->spec); + image_error ("Error loading XBM image "uLSQM"%s"uRSQM, file); return 0; } @@ -3640,6 +3646,7 @@ xpm_load (struct frame *f, struct image *img) return 0; } + file = ENCODE_FILE (file); #ifdef HAVE_NTGUI #ifdef WINDOWSNT /* FILE is encoded in UTF-8, but image libraries on Windows @@ -4290,21 +4297,19 @@ xpm_load (struct frame *f, file_name = image_spec_value (img->spec, QCfile, NULL); if (STRINGP (file_name)) { - Lisp_Object file; - unsigned char *contents; - ptrdiff_t size; - - file = x_find_image_file (file_name); + int fd; + Lisp_Object file = x_find_image_fd (file_name, &fd); if (!STRINGP (file)) { image_error ("Cannot find image file "uLSQM"%s"uRSQM, file_name); return 0; } - contents = slurp_file (SSDATA (file), &size); + ptrdiff_t size; + unsigned char *contents = slurp_file (fd, &size); if (contents == NULL) { - image_error ("Error loading XPM image "uLSQM"%s"uRSQM, img->spec); + image_error ("Error loading XPM image "uLSQM"%s"uRSQM, file); return 0; } @@ -5253,11 +5258,10 @@ pbm_load (struct frame *f, struct image *img) bool raw_p; int x, y; int width, height, max_color_idx = 0; - Lisp_Object file, specified_file; + Lisp_Object specified_file; enum {PBM_MONO, PBM_GRAY, PBM_COLOR} type; unsigned char *contents = NULL; unsigned char *end, *p; - ptrdiff_t size; #ifdef USE_CAIRO unsigned char *data = 0; uint32_t *dataptr; @@ -5269,7 +5273,8 @@ pbm_load (struct frame *f, struct image *img) if (STRINGP (specified_file)) { - file = x_find_image_file (specified_file); + int fd; + Lisp_Object file = x_find_image_fd (specified_file, &fd); if (!STRINGP (file)) { image_error ("Cannot find image file "uLSQM"%s"uRSQM, @@ -5277,7 +5282,8 @@ pbm_load (struct frame *f, struct image *img) return 0; } - contents = slurp_file (SSDATA (file), &size); + ptrdiff_t size; + contents = slurp_file (fd, &size); if (contents == NULL) { image_error ("Error reading "uLSQM"%s"uRSQM, file); @@ -5878,7 +5884,7 @@ struct png_load_context static bool png_load_body (struct frame *f, struct image *img, struct png_load_context *c) { - Lisp_Object file, specified_file; + Lisp_Object specified_file; Lisp_Object specified_data; int x, y; ptrdiff_t i; @@ -5909,7 +5915,8 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) if (NILP (specified_data)) { - file = x_find_image_file (specified_file); + int fd; + Lisp_Object file = x_find_image_fd (specified_file, &fd); if (!STRINGP (file)) { image_error ("Cannot find image file "uLSQM"%s"uRSQM, @@ -5918,7 +5925,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c) } /* Open the image file. */ - fp = emacs_fopen (SSDATA (file), "rb"); + fp = fdopen (fd, "rb"); if (!fp) { image_error ("Cannot open image file "uLSQM"%s"uRSQM, file); @@ -6654,7 +6661,7 @@ static bool jpeg_load_body (struct frame *f, struct image *img, struct my_jpeg_error_mgr *mgr) { - Lisp_Object file, specified_file; + Lisp_Object specified_file; Lisp_Object specified_data; /* The 'volatile' silences a bogus diagnostic; see GCC bug 54561. */ FILE * IF_LINT (volatile) fp = NULL; @@ -6674,7 +6681,8 @@ jpeg_load_body (struct frame *f, struct image *img, if (NILP (specified_data)) { - file = x_find_image_file (specified_file); + int fd; + Lisp_Object file = x_find_image_fd (specified_file, &fd); if (!STRINGP (file)) { image_error ("Cannot find image file "uLSQM"%s"uRSQM, @@ -6682,7 +6690,7 @@ jpeg_load_body (struct frame *f, struct image *img, return 0; } - fp = emacs_fopen (SSDATA (file), "rb"); + fp = fdopen (fd, "rb"); if (fp == NULL) { image_error ("Cannot open "uLSQM"%s"uRSQM, file); @@ -7172,7 +7180,7 @@ tiff_warning_handler (const char *title, const char *format, va_list ap) static bool tiff_load (struct frame *f, struct image *img) { - Lisp_Object file, specified_file; + Lisp_Object specified_file; Lisp_Object specified_data; TIFF *tiff; int width, height, x, y, count; @@ -7191,19 +7199,21 @@ tiff_load (struct frame *f, struct image *img) if (NILP (specified_data)) { /* Read from a file */ - file = x_find_image_file (specified_file); + Lisp_Object file = x_find_image_file (specified_file); if (!STRINGP (file)) { image_error ("Cannot find image file "uLSQM"%s"uRSQM, specified_file); return 0; } + + Lisp_Object encoded_file = ENCODE_FILE (file); # ifdef WINDOWSNT - file = ansi_encode_filename (file); + encoded_file = ansi_encode_filename (encoded_file); # endif /* Try to open the image file. */ - tiff = TIFFOpen (SSDATA (file), "r"); + tiff = TIFFOpen (SSDATA (encoded_file), "r"); if (tiff == NULL) { image_error ("Cannot open "uLSQM"%s"uRSQM, file); @@ -7605,7 +7615,6 @@ static const int interlace_increment[] = {8, 8, 4, 2}; static bool gif_load (struct frame *f, struct image *img) { - Lisp_Object file; int rc, width, height, x, y, i, j; ColorMapObject *gif_color_map; unsigned long pixel_colors[256]; @@ -7626,27 +7635,29 @@ gif_load (struct frame *f, struct image *img) if (NILP (specified_data)) { - file = x_find_image_file (specified_file); + Lisp_Object file = x_find_image_file (specified_file); if (!STRINGP (file)) { image_error ("Cannot find image file "uLSQM"%s"uRSQM, specified_file); return 0; } + + Lisp_Object encoded_file = ENCODE_FILE (file); #ifdef WINDOWSNT - file = ansi_encode_filename (file); + encoded_file = ansi_encode_filename (encoded_file); #endif /* Open the GIF file. */ #if GIFLIB_MAJOR < 5 - gif = DGifOpenFileName (SSDATA (file)); + gif = DGifOpenFileName (SSDATA (encoded_file)); if (gif == NULL) { image_error ("Cannot open "uLSQM"%s"uRSQM, file); return 0; } #else - gif = DGifOpenFileName (SSDATA (file), &gif_err); + gif = DGifOpenFileName (SSDATA (encoded_file), &gif_err); if (gif == NULL) { image_error ("Cannot open "uLSQM"%s"uRSQM": %s", @@ -8818,14 +8829,13 @@ imagemagick_load (struct frame *f, struct image *img) file_name = image_spec_value (img->spec, QCfile, NULL); if (STRINGP (file_name)) { - Lisp_Object file; - - file = x_find_image_file (file_name); + Lisp_Object file = x_find_image_file (file_name); if (!STRINGP (file)) { image_error ("Cannot find image file "uLSQM"%s"uRSQM, file_name); return 0; } + file = ENCODE_FILE (file); #ifdef WINDOWSNT file = ansi_encode_filename (file); #endif @@ -9097,11 +9107,8 @@ svg_load (struct frame *f, struct image *img) file_name = image_spec_value (img->spec, QCfile, NULL); if (STRINGP (file_name)) { - Lisp_Object file; - unsigned char *contents; - ptrdiff_t size; - - file = x_find_image_file (file_name); + int fd; + Lisp_Object file = x_find_image_fd (file_name, &fd); if (!STRINGP (file)) { image_error ("Cannot find image file "uLSQM"%s"uRSQM, file_name); @@ -9109,14 +9116,16 @@ svg_load (struct frame *f, struct image *img) } /* Read the entire file into memory. */ - contents = slurp_file (SSDATA (file), &size); + ptrdiff_t size; + unsigned char *contents = slurp_file (fd, &size); if (contents == NULL) { - image_error ("Error loading SVG image "uLSQM"%s"uRSQM, img->spec); + image_error ("Error loading SVG image "uLSQM"%s"uRSQM, file); return 0; } /* If the file was slurped into memory properly, parse it. */ - success_p = svg_load_image (f, img, contents, size, SSDATA (file)); + success_p = svg_load_image (f, img, contents, size, + SSDATA (ENCODE_FILE (file))); xfree (contents); } /* Else its not a file, its a lisp object. Load the image from a diff --git a/src/lread.c b/src/lread.c index ebd594c1a16..77a62118a39 100644 --- a/src/lread.c +++ b/src/lread.c @@ -1403,7 +1403,8 @@ directories, make sure the PREDICATE function returns `dir-ok' for them. */) SUFFIXES is a list of strings containing possible suffixes. The empty suffix is automatically added if the list is empty. - PREDICATE non-nil means don't open the files, + PREDICATE t means the files are binary. + PREDICATE non-nil and non-t means don't open the files, just look for one that satisfies the predicate. In this case, return 1 on success. The predicate can be a lisp function or an integer to pass to `access' (in which case file-name-handlers @@ -1418,7 +1419,7 @@ directories, make sure the PREDICATE function returns `dir-ok' for them. */) If NEWER is true, try all SUFFIXes and return the result for the newest file that exists. Does not apply to remote files, - or if PREDICATE is specified. */ + or if a non-nil and non-t PREDICATE is specified. */ int openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, @@ -1520,10 +1521,11 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, else string = make_string (fn, fnlen); handler = Ffind_file_name_handler (string, Qfile_exists_p); - if ((!NILP (handler) || !NILP (predicate)) && !NATNUMP (predicate)) + if ((!NILP (handler) || (!NILP (predicate) && !EQ (predicate, Qt))) + && !NATNUMP (predicate)) { bool exists; - if (NILP (predicate)) + if (NILP (predicate) || EQ (predicate, Qt)) exists = !NILP (Ffile_readable_p (string)); else { @@ -1577,7 +1579,8 @@ openp (Lisp_Object path, Lisp_Object str, Lisp_Object suffixes, } else { - fd = emacs_open (pfn, O_RDONLY, 0); + int oflags = O_RDONLY + (NILP (predicate) ? 0 : O_BINARY); + fd = emacs_open (pfn, oflags, 0); if (fd < 0) { if (errno != ENOENT) diff --git a/src/nsimage.m b/src/nsimage.m index 13e8504f460..5d0871bc1a9 100644 --- a/src/nsimage.m +++ b/src/nsimage.m @@ -169,6 +169,7 @@ ns_set_alpha (void *img, int x, int y, unsigned char a) found = x_find_image_file (file); if (!STRINGP (found)) return nil; + found = ENCODE_FILE (found); image = [[EmacsImage alloc] initByReferencingFile: [NSString stringWithUTF8String: SSDATA (found)]]; diff --git a/src/xfns.c b/src/xfns.c index 18fb343efd6..3ef6762bb92 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -548,7 +548,7 @@ xg_set_icon (struct frame *f, Lisp_Object file) { GdkPixbuf *pixbuf; GError *err = NULL; - char *filename = SSDATA (found); + char *filename = SSDATA (ENCODE_FILE (found)); block_input (); pixbuf = gdk_pixbuf_new_from_file (filename, &err); -- 2.39.2