@@ -48,8 +48,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
48
48
49
49
#include <err.h>
50
50
#include <errno.h>
51
- #include <stdio .h>
51
+ #include <fcntl .h>
52
52
#include <stdint.h>
53
+ #include <stdio.h>
53
54
#include <stdlib.h>
54
55
#include <string.h>
55
56
#include <time.h>
@@ -68,15 +69,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
68
69
69
70
static void initXAndImlib (const char * , int );
70
71
static void uninitXAndImlib (void );
71
- static void scrotSaveImage (const char * );
72
+ static void scrotSaveImage (int , const char * );
72
73
static Imlib_Image scrotGrabFocused (void );
73
74
static Imlib_Image scrotGrabAutoselect (void );
74
75
static long miliToNanoSec (int );
75
76
static Imlib_Image scrotGrabShotMulti (void );
76
77
static Imlib_Image scrotGrabShotMonitor (void );
77
78
static Imlib_Image scrotGrabStackWindows (void );
78
79
static Imlib_Image scrotGrabShot (void );
79
- static void scrotCheckIfOverwriteFile (char * * );
80
+ static int scrotCheckIfOverwriteFile (char * * );
80
81
static void scrotExecApp (Imlib_Image , struct tm * , char * , char * );
81
82
static char * imPrintf (const char * , struct tm * , const char * , const char * ,
82
83
Imlib_Image );
@@ -102,6 +103,7 @@ int main(int argc, char *argv[])
102
103
char * filenameThumb = NULL ;
103
104
struct timespec timeStamp ;
104
105
struct tm * tm ;
106
+ int fd ;
105
107
106
108
/* Get the time ASAP to reduce the timing error in case --delay is used. */
107
109
opt .delayStart = clockNow ();
@@ -155,9 +157,8 @@ int main(int argc, char *argv[])
155
157
imlib_image_attach_data_value ("compression" , NULL , opt .compression , NULL );
156
158
157
159
filenameIM = imPrintf (opt .outputFile , tm , NULL , NULL , image );
158
- scrotCheckIfOverwriteFile (& filenameIM );
159
-
160
- scrotSaveImage (filenameIM );
160
+ fd = scrotCheckIfOverwriteFile (& filenameIM );
161
+ scrotSaveImage (fd , filenameIM );
161
162
162
163
if (opt .thumb != THUMB_DISABLED ) {
163
164
int cwidth , cheight ;
@@ -195,8 +196,8 @@ int main(int argc, char *argv[])
195
196
imlib_image_set_format (opt .format );
196
197
197
198
filenameThumb = imPrintf (opt .thumbFile , tm , NULL , NULL , thumbnail );
198
- scrotCheckIfOverwriteFile (& filenameThumb );
199
- scrotSaveImage (filenameThumb );
199
+ fd = scrotCheckIfOverwriteFile (& filenameThumb );
200
+ scrotSaveImage (fd , filenameThumb );
200
201
imlib_free_image_and_decache ();
201
202
}
202
203
}
@@ -254,9 +255,11 @@ static void uninitXAndImlib(void)
254
255
}
255
256
}
256
257
257
- static void scrotSaveImage (const char * filename )
258
+ // save image to fd, filename only used for logging
259
+ // fd will be closed after calling this function
260
+ static void scrotSaveImage (int fd , const char * filename )
258
261
{
259
- imlib_save_image ( filename );
262
+ imlib_save_image_fd ( fd , filename );
260
263
int imErr = imlib_get_error ();
261
264
if (imErr ) {
262
265
const char * errmsg = imlib_strerror (imErr );
@@ -537,43 +540,50 @@ static void scrotGrabMousePointer(Imlib_Image image, const int xOffset,
537
540
XFree (xcim );
538
541
}
539
542
540
- static void scrotCheckIfOverwriteFile (char * * filename )
543
+ static int scrotCheckIfOverwriteFile (char * * filename )
541
544
{
542
- if (opt .overwrite )
543
- return ;
544
-
545
- if (access (* filename , F_OK ) == -1 )
546
- return ;
547
-
548
- const size_t maxCounter = 999 ;
549
- char fmt [5 ]; // _000 + NUL byte
550
- const size_t slen = strlen (* filename );
551
- const size_t nalloc = slen + sizeof (fmt );
552
-
553
- char * ext ;
554
- size_t extLength = scrotHaveFileExtension (* filename , & ext );
555
-
556
- char * newName = ecalloc (nalloc , sizeof (* newName ));
557
- memcpy (newName , * filename , slen - extLength );
558
- char * ptr = newName + (slen - extLength );
559
-
560
- size_t counter = 0 ;
561
- do {
562
- snprintf (fmt , sizeof (fmt ), "_%03zu" , counter ++ );
563
- memcpy (ptr , fmt , sizeof (fmt ));
564
- memcpy (ptr + sizeof (fmt ) - 1 , ext , extLength );
565
- } while ((counter < maxCounter ) && !access (newName , F_OK ));
566
-
567
- scrotAssert (newName [nalloc - 1 ] == '\0' );
545
+ if (strcmp (* filename , "-" ) == 0 )
546
+ return 1 ;
547
+
548
+ int flags = O_RDWR | O_CREAT | (opt .overwrite ? O_TRUNC : O_EXCL );
549
+ int fd = open (* filename , flags , 0644 );
550
+ if (!opt .overwrite && fd < 0 && errno == EEXIST ) {
551
+ const size_t maxCounter = 999 ;
552
+ char fmt [5 ]; // _000 + NUL byte
553
+ const size_t slen = strlen (* filename );
554
+ const size_t nalloc = slen + sizeof (fmt );
555
+
556
+ char * ext ;
557
+ size_t extLength = scrotHaveFileExtension (* filename , & ext );
558
+
559
+ char * newName = ecalloc (nalloc , sizeof (* newName ));
560
+ memcpy (newName , * filename , slen - extLength );
561
+ char * ptr = newName + (slen - extLength );
562
+
563
+ size_t counter = 0 ;
564
+ do {
565
+ snprintf (fmt , sizeof (fmt ), "_%03zu" , counter ++ );
566
+ memcpy (ptr , fmt , sizeof (fmt ));
567
+ memcpy (ptr + sizeof (fmt ) - 1 , ext , extLength );
568
+ fd = open (newName , flags , 0644 );
569
+ } while ((counter < maxCounter ) && fd < 0 && errno == EEXIST );
570
+ scrotAssert (newName [nalloc - 1 ] == '\0' );
571
+
572
+ if (counter == maxCounter ) {
573
+ errx (EXIT_FAILURE , "scrot can no longer generate new file names.\n"
574
+ "The last attempt is %s" , newName );
575
+ }
568
576
569
- if (counter == maxCounter ) {
570
- errx (EXIT_FAILURE , "scrot can no longer generate new file names.\n"
571
- "The last attempt is %s" , newName );
577
+ int saved_errno = errno ; // avoid errno getting potentially clobbered
578
+ warnx ("`%s` already exists, attempting `%s` instead" , * filename , newName );
579
+ free (* filename );
580
+ * filename = newName ;
581
+ errno = saved_errno ;
572
582
}
573
583
574
- warnx ( "`%s` already exists, attempting `%s` instead" , * filename , newName );
575
- free ( * filename );
576
- * filename = newName ;
584
+ if ( fd < 0 )
585
+ err ( EXIT_FAILURE , "couldn't open file %s" , * filename );
586
+ return fd ;
577
587
}
578
588
579
589
static int scrotMatchWindowClassName (Window target )
0 commit comments