diff options
| -rw-r--r-- | tools/idevicescreenshot.c | 75 |
1 files changed, 57 insertions, 18 deletions
diff --git a/tools/idevicescreenshot.c b/tools/idevicescreenshot.c index 75a69ce..f33e83e 100644 --- a/tools/idevicescreenshot.c +++ b/tools/idevicescreenshot.c | |||
| @@ -29,7 +29,9 @@ | |||
| 29 | #include <string.h> | 29 | #include <string.h> |
| 30 | #include <stdlib.h> | 30 | #include <stdlib.h> |
| 31 | #include <errno.h> | 31 | #include <errno.h> |
| 32 | #include <math.h> | ||
| 32 | #include <time.h> | 33 | #include <time.h> |
| 34 | #include <unistd.h> | ||
| 33 | #ifndef WIN32 | 35 | #ifndef WIN32 |
| 34 | #include <signal.h> | 36 | #include <signal.h> |
| 35 | #endif | 37 | #endif |
| @@ -38,6 +40,7 @@ | |||
| 38 | #include <libimobiledevice/lockdown.h> | 40 | #include <libimobiledevice/lockdown.h> |
| 39 | #include <libimobiledevice/screenshotr.h> | 41 | #include <libimobiledevice/screenshotr.h> |
| 40 | 42 | ||
| 43 | void get_image_filename(char *imgdata, char **filename); | ||
| 41 | void print_usage(int argc, char **argv); | 44 | void print_usage(int argc, char **argv); |
| 42 | 45 | ||
| 43 | int main(int argc, char **argv) | 46 | int main(int argc, char **argv) |
| @@ -117,21 +120,7 @@ int main(int argc, char **argv) | |||
| 117 | char *imgdata = NULL; | 120 | char *imgdata = NULL; |
| 118 | uint64_t imgsize = 0; | 121 | uint64_t imgsize = 0; |
| 119 | if (screenshotr_take_screenshot(shotr, &imgdata, &imgsize) == SCREENSHOTR_E_SUCCESS) { | 122 | if (screenshotr_take_screenshot(shotr, &imgdata, &imgsize) == SCREENSHOTR_E_SUCCESS) { |
| 120 | if (!filename) { | 123 | get_image_filename(imgdata, &filename); |
| 121 | const char *fileext = NULL; | ||
| 122 | if (memcmp(imgdata, "\x89PNG", 4) == 0) { | ||
| 123 | fileext = ".png"; | ||
| 124 | } else if (memcmp(imgdata, "MM\x00*", 4) == 0) { | ||
| 125 | fileext = ".tiff"; | ||
| 126 | } else { | ||
| 127 | printf("WARNING: screenshot data has unexpected image format.\n"); | ||
| 128 | fileext = ".dat"; | ||
| 129 | } | ||
| 130 | time_t now = time(NULL); | ||
| 131 | filename = (char*)malloc(36); | ||
| 132 | size_t pos = strftime(filename, 36, "screenshot-%Y-%m-%d-%H-%M-%S", gmtime(&now)); | ||
| 133 | sprintf(filename+pos, "%s", fileext); | ||
| 134 | } | ||
| 135 | FILE *f = fopen(filename, "wb"); | 124 | FILE *f = fopen(filename, "wb"); |
| 136 | if (f) { | 125 | if (f) { |
| 137 | if (fwrite(imgdata, 1, (size_t)imgsize, f) == (size_t)imgsize) { | 126 | if (fwrite(imgdata, 1, (size_t)imgsize, f) == (size_t)imgsize) { |
| @@ -162,6 +151,53 @@ int main(int argc, char **argv) | |||
| 162 | return result; | 151 | return result; |
| 163 | } | 152 | } |
| 164 | 153 | ||
| 154 | void get_image_filename(char *imgdata, char **filename) | ||
| 155 | { | ||
| 156 | // If the provided filename already has an extension, use it as is. | ||
| 157 | if (*filename) { | ||
| 158 | char *last_dot = strrchr(*filename, '.'); | ||
| 159 | if (last_dot && !strchr(last_dot, '/')) { | ||
| 160 | return; | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | // Find the appropriate file extension for the filename. | ||
| 165 | const char *fileext = NULL; | ||
| 166 | if (memcmp(imgdata, "\x89PNG", 4) == 0) { | ||
| 167 | fileext = ".png"; | ||
| 168 | } else if (memcmp(imgdata, "MM\x00*", 4) == 0) { | ||
| 169 | fileext = ".tiff"; | ||
| 170 | } else { | ||
| 171 | printf("WARNING: screenshot data has unexpected image format.\n"); | ||
| 172 | fileext = ".dat"; | ||
| 173 | } | ||
| 174 | |||
| 175 | // If a filename without an extension is provided, append the extension. | ||
| 176 | // Otherwise, generate a filename based on the current time. | ||
| 177 | char *basename = NULL; | ||
| 178 | if (*filename) { | ||
| 179 | basename = (char*)malloc(strlen(*filename) + 1); | ||
| 180 | strcpy(basename, *filename); | ||
| 181 | free(*filename); | ||
| 182 | } else { | ||
| 183 | time_t now = time(NULL); | ||
| 184 | basename = (char*)malloc(32); | ||
| 185 | strftime(basename, 31, "screenshot-%Y-%m-%d-%H-%M-%S", gmtime(&now)); | ||
| 186 | } | ||
| 187 | |||
| 188 | // Ensure the filename is unique on disk. | ||
| 189 | char *unique_filename = (char*)malloc(strlen(basename) + strlen(fileext) + 1); | ||
| 190 | sprintf(unique_filename, "%s%s", basename, fileext); | ||
| 191 | int i; | ||
| 192 | for (i = 2; access(unique_filename, F_OK) != -1; i++) { | ||
| 193 | free(unique_filename); | ||
| 194 | unique_filename = (char*)malloc(strlen(basename) + strlen(fileext) + floor(log10(i)) + 3); | ||
| 195 | sprintf(unique_filename, "%s-%d%s", basename, i, fileext); | ||
| 196 | } | ||
| 197 | *filename = unique_filename; | ||
| 198 | free(basename); | ||
| 199 | } | ||
| 200 | |||
| 165 | void print_usage(int argc, char **argv) | 201 | void print_usage(int argc, char **argv) |
| 166 | { | 202 | { |
| 167 | char *name = NULL; | 203 | char *name = NULL; |
| @@ -169,10 +205,13 @@ void print_usage(int argc, char **argv) | |||
| 169 | name = strrchr(argv[0], '/'); | 205 | name = strrchr(argv[0], '/'); |
| 170 | printf("Usage: %s [OPTIONS] [FILE]\n", (name ? name + 1: argv[0])); | 206 | printf("Usage: %s [OPTIONS] [FILE]\n", (name ? name + 1: argv[0])); |
| 171 | printf("\n"); | 207 | printf("\n"); |
| 172 | printf("Gets a screenshot from a device.\n"); | 208 | printf("Gets a screenshot from a connected device.\n"); |
| 173 | printf("\n"); | 209 | printf("\n"); |
| 174 | printf("The screenshot is saved as a TIFF image with the given FILE name,\n"); | 210 | printf("The image is in PNG format for iOS 9+ and otherwise in TIFF format.\n"); |
| 175 | printf("where the default name is \"screenshot-DATE.tiff\", e.g.:\n"); | 211 | printf("The screenshot is saved as an image with the given FILE name.\n"); |
| 212 | printf("If FILE has no extension, FILE will be a prefix of the saved filename.\n"); | ||
| 213 | printf("If FILE is not specified, \"screenshot-DATE\", will be used as a prefix\n"); | ||
| 214 | printf("of the filename, e.g.:\n"); | ||
| 176 | printf(" ./screenshot-2013-12-31-23-59-59.tiff\n"); | 215 | printf(" ./screenshot-2013-12-31-23-59-59.tiff\n"); |
| 177 | printf("\n"); | 216 | printf("\n"); |
| 178 | printf("NOTE: A mounted developer disk image is required on the device, otherwise\n"); | 217 | printf("NOTE: A mounted developer disk image is required on the device, otherwise\n"); |
