Skip to content

Commit c6f9138

Browse files
committed
use fd for saving images
Closes: #244 Closes: #246
1 parent 95ae608 commit c6f9138

File tree

3 files changed

+56
-59
lines changed

3 files changed

+56
-59
lines changed

TODO.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ transition for users and avoid depending on bleeding edge library versions.
6161

6262
- [x] Require Imlib2 v1.11.0
6363
- [x] Document minimum version of other dependencies [#307](https://github.com/resurrecting-open-source-projects/scrot/issues/307)
64-
- [ ] Use file descriptors when saving images
65-
- [ ] https://github.com/resurrecting-open-source-projects/scrot/issues/244
66-
- [ ] https://github.com/resurrecting-open-source-projects/scrot/issues/246
64+
- [x] Use file descriptors when saving images
65+
- [x] https://github.com/resurrecting-open-source-projects/scrot/issues/244
66+
- [x] https://github.com/resurrecting-open-source-projects/scrot/issues/246
6767
- [ ] https://github.com/resurrecting-open-source-projects/scrot/issues/226
6868
- [x] Remove deprecated features
6969
- [x] --note [#236](https://github.com/resurrecting-open-source-projects/scrot/issues/236)

src/options.c

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -361,18 +361,6 @@ static void optionsParseLine(char *optarg)
361361
} /* while */
362362
}
363363

364-
static const char *getPathOfStdout(void)
365-
{
366-
const char *paths[] = { "/dev/stdout", "/dev/fd/1", "/proc/self/fd/1" };
367-
368-
for (size_t i = 0; i < ARRAY_COUNT(paths); ++i) {
369-
if (access(paths[i], W_OK) == 0)
370-
return paths[i];
371-
}
372-
err(EXIT_FAILURE, "access to stdout failed");
373-
return 0; /* silence tcc warning */
374-
}
375-
376364
void optionsParse(int argc, char *argv[])
377365
{
378366
int optch;
@@ -526,7 +514,6 @@ void optionsParse(int argc, char *argv[])
526514
if (strcmp(opt.outputFile, "-") == 0) {
527515
opt.overwrite = true;
528516
opt.thumb = THUMB_DISABLED;
529-
opt.outputFile = getPathOfStdout();
530517
}
531518

532519
size_t outputFileLen = strlen(opt.outputFile);

src/scrot.c

Lines changed: 53 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
4848

4949
#include <err.h>
5050
#include <errno.h>
51-
#include <stdio.h>
51+
#include <fcntl.h>
5252
#include <stdint.h>
53+
#include <stdio.h>
5354
#include <stdlib.h>
5455
#include <string.h>
5556
#include <time.h>
@@ -68,15 +69,15 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
6869

6970
static void initXAndImlib(const char *, int);
7071
static void uninitXAndImlib(void);
71-
static void scrotSaveImage(const char *);
72+
static void scrotSaveImage(int, const char *);
7273
static Imlib_Image scrotGrabFocused(void);
7374
static Imlib_Image scrotGrabAutoselect(void);
7475
static long miliToNanoSec(int);
7576
static Imlib_Image scrotGrabShotMulti(void);
7677
static Imlib_Image scrotGrabShotMonitor(void);
7778
static Imlib_Image scrotGrabStackWindows(void);
7879
static Imlib_Image scrotGrabShot(void);
79-
static void scrotCheckIfOverwriteFile(char **);
80+
static int scrotCheckIfOverwriteFile(char **);
8081
static void scrotExecApp(Imlib_Image, struct tm *, char *, char *);
8182
static char *imPrintf(const char *, struct tm *, const char *, const char *,
8283
Imlib_Image);
@@ -102,6 +103,7 @@ int main(int argc, char *argv[])
102103
char *filenameThumb = NULL;
103104
struct timespec timeStamp;
104105
struct tm *tm;
106+
int fd;
105107

106108
/* Get the time ASAP to reduce the timing error in case --delay is used. */
107109
opt.delayStart = clockNow();
@@ -155,9 +157,8 @@ int main(int argc, char *argv[])
155157
imlib_image_attach_data_value("compression", NULL, opt.compression, NULL);
156158

157159
filenameIM = imPrintf(opt.outputFile, tm, NULL, NULL, image);
158-
scrotCheckIfOverwriteFile(&filenameIM);
159-
160-
scrotSaveImage(filenameIM);
160+
fd = scrotCheckIfOverwriteFile(&filenameIM);
161+
scrotSaveImage(fd, filenameIM);
161162

162163
if (opt.thumb != THUMB_DISABLED) {
163164
int cwidth, cheight;
@@ -195,8 +196,8 @@ int main(int argc, char *argv[])
195196
imlib_image_set_format(opt.format);
196197

197198
filenameThumb = imPrintf(opt.thumbFile, tm, NULL, NULL, thumbnail);
198-
scrotCheckIfOverwriteFile(&filenameThumb);
199-
scrotSaveImage(filenameThumb);
199+
fd = scrotCheckIfOverwriteFile(&filenameThumb);
200+
scrotSaveImage(fd, filenameThumb);
200201
imlib_free_image_and_decache();
201202
}
202203
}
@@ -254,9 +255,11 @@ static void uninitXAndImlib(void)
254255
}
255256
}
256257

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)
258261
{
259-
imlib_save_image(filename);
262+
imlib_save_image_fd(fd, filename);
260263
int imErr = imlib_get_error();
261264
if (imErr) {
262265
const char *errmsg = imlib_strerror(imErr);
@@ -537,43 +540,50 @@ static void scrotGrabMousePointer(Imlib_Image image, const int xOffset,
537540
XFree(xcim);
538541
}
539542

540-
static void scrotCheckIfOverwriteFile(char **filename)
543+
static int scrotCheckIfOverwriteFile(char **filename)
541544
{
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+
}
568576

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;
572582
}
573583

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;
577587
}
578588

579589
static int scrotMatchWindowClassName(Window target)

0 commit comments

Comments
 (0)