Skip to content
This repository was archived by the owner on Dec 31, 2025. It is now read-only.
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 71 additions & 2 deletions fswebcam.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ typedef struct {
char *filename;
char format;
char compression;
uint8_t mkdir_output_file;

} fswebcam_config_t;

Expand Down Expand Up @@ -440,6 +441,59 @@ gdImage* fswc_gdImageDuplicate(gdImage* src)
return(dst);
}

int fswc_create_output_dir(char *filename)
{
/* Step through the filename checking each segment of the path in turn.
* If one does not exist, try creating it. Return an error or 0 if
* all paths created successfully. Modifies but repairs filename */
int pos;
int len = strlen(filename);
int result;
struct stat st = {0};

/* First move the 'length' back to the last slash, since we don't want to
* create a directory with the name of the filename */
for (len > 0; filename[len] != '/'; len--);
if (len == 0)
{
return 0;
}
/* We have to start with at least _some_ path, hence pos = 1 */
for (pos = 1; pos < len; pos++)
{
/* Look for a / character that divides the path. */
for (; pos <= len && filename[pos] != '/'; pos++);
if (pos > len) {
/* If went past the last directory, then we've got no more path
* to create. */
break;
}
/* Terminate the string here for now */
filename[pos] = '\0';
/* Now stat and create if not found */
result = stat(filename, &st);
/* Can't put / back until after mkdir */
if (result == -1)
{
if (errno == ENOENT) {
result = mkdir(filename, 0700);
MSG("Creating path for '%s'", filename);
filename[pos] = '/';
if (result == -1)
{
return -1;
}
}
else
{
return -1;
}
}
filename[pos] = '/';
}
return 0;
}

int fswc_output(fswebcam_config_t *config, char *name, gdImage *image)
{
char filename[FILENAME_MAX];
Expand Down Expand Up @@ -480,13 +534,22 @@ int fswc_output(fswebcam_config_t *config, char *name, gdImage *image)
{
/* Can't load the font - display a warning */
WARN("Unable to load font '%s': %s", config->font, err);
WARN("Disabling the the banner.");
WARN("Disabling the banner.");
}
}

/* Draw the overlay. */
fswc_draw_overlay(config, config->overlay, im);

/* Do we need to check that the output directory exists? */
if (config->mkdir_output_file)
{
int err = fswc_create_output_dir(filename);
if (err < 0) {
WARN("Unable to create path to file '%s': %s", filename, strerror(errno));
}
}

/* Write to a file if a filename was given, otherwise stdout. */
if(strncmp(name, "-", 2)) f = fopen(filename, "wb");
else f = stdout;
Expand Down Expand Up @@ -1179,6 +1242,7 @@ int fswc_usage()
#endif
" --save <filename> Save image to file.\n"
" --exec <command> Execute a command and wait for it to complete.\n"
" -m, --mkdir Make all the directories in the path\n"
"\n");

return(0);
Expand Down Expand Up @@ -1427,9 +1491,10 @@ int fswc_getopts(fswebcam_config_t *config, int argc, char *argv[])
#endif
{"save", required_argument, 0, OPT_SAVE},
{"exec", required_argument, 0, OPT_EXEC},
{"mkdir", no_argument, 0, 'm'},
{0, 0, 0, 0}
};
char *opts = "-qc:vl:bL:d:i:t:f:D:T:r:F:s:S:p:R";
char *opts = "-qc:vl:bL:d:i:t:f:D:T:r:F:s:S:p:Rm";

s.opts = opts;
s.long_opts = long_opts;
Expand Down Expand Up @@ -1465,6 +1530,7 @@ int fswc_getopts(fswebcam_config_t *config, int argc, char *argv[])
config->dumpframe = NULL;
config->jobs = 0;
config->job = NULL;
config->mkdir_output_file = 0;

/* Don't report errors. */
opterr = 0;
Expand Down Expand Up @@ -1574,6 +1640,9 @@ int fswc_getopts(fswebcam_config_t *config, int argc, char *argv[])
case 'R':
config->use_read = -1;
break;
case 'm':
config->mkdir_output_file = 1;
break;
case OPT_LIST_FORMATS:
config->list |= SRC_LIST_FORMATS;
break;
Expand Down