1 /**
2 * Copyright (C) ARM Limited 2010-2012. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
9 #include <sys/stat.h>
10 #include <sys/types.h>
11 #include <dirent.h>
12 #include <string.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include "LocalCapture.h"
16 #include "SessionData.h"
17 #include "Logging.h"
18 #include "OlyUtility.h"
20 extern void handleException();
22 LocalCapture::LocalCapture() {}
24 LocalCapture::~LocalCapture() {}
26 void LocalCapture::createAPCDirectory(char* target_path, char* name) {
27 gSessionData->mAPCDir = createUniqueDirectory(target_path, ".apc", name);
28 if ((removeDirAndAllContents(gSessionData->mAPCDir) != 0 || mkdir(gSessionData->mAPCDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)) {
29 logg->logError(__FILE__, __LINE__, "Unable to create directory %s", gSessionData->mAPCDir);
30 handleException();
31 }
32 }
34 void LocalCapture::write(char* string) {
35 char* file = (char*)malloc(PATH_MAX);
37 // Set full path
38 snprintf(file, PATH_MAX, "%s/session.xml", gSessionData->mAPCDir);
40 // Write the file
41 if (util->writeToDisk(file, string) < 0) {
42 logg->logError(__FILE__, __LINE__, "Error writing %s\nPlease verify the path.", file);
43 handleException();
44 }
46 free(file);
47 }
49 char* LocalCapture::createUniqueDirectory(const char* initialPath, const char* ending, char* title) {
50 int i;
51 char* output;
52 char* path = (char*)malloc(PATH_MAX);
54 // Ensure the path is an absolute path, i.e. starts with a slash
55 if (initialPath == 0 || strlen(initialPath) == 0) {
56 if (getcwd(path, PATH_MAX) == 0) {
57 logg->logMessage("Unable to retrive the current working directory");
58 }
59 strncat(path, "/@F_@N", PATH_MAX - strlen(path) - 1);
60 } else if (initialPath[0] != '/') {
61 if (getcwd(path, PATH_MAX) == 0) {
62 logg->logMessage("Unable to retrive the current working directory");
63 }
64 strncat(path, "/", PATH_MAX - strlen(path) - 1);
65 strncat(path, initialPath, PATH_MAX - strlen(path) - 1);
66 } else {
67 strncpy(path, initialPath, PATH_MAX);
68 path[PATH_MAX - 1] = 0; // strncpy does not guarantee a null-terminated string
69 }
71 // Convert to uppercase
72 replaceAll(path, "@f", "@F", PATH_MAX);
73 replaceAll(path, "@n", "@N", PATH_MAX);
75 // Replace @F with the session xml title
76 replaceAll(path, "@F", title, PATH_MAX);
78 // Add ending if it is not already there
79 if (strcmp(&path[strlen(path) - strlen(ending)], ending) != 0) {
80 strncat(path, ending, PATH_MAX - strlen(path) - 1);
81 }
83 // Replace @N with a unique integer
84 if (strstr(path, "@N")) {
85 char* tempPath = (char*)malloc(PATH_MAX);
86 for (i = 1; i < 1000; i++) {
87 char number[4];
88 snprintf(number, sizeof(number), "%03d", i);
89 strcpy(tempPath, path);
90 replaceAll(tempPath, "@N", number, PATH_MAX);
91 struct stat mFileInfo;
92 if (stat(tempPath, &mFileInfo) != 0) {
93 // if the direcotry does not exist, break
94 break;
95 }
96 }
98 if (i == 1000) {
99 logg->logError(__FILE__, __LINE__, "Unable to create .apc directory, please delete older directories.");
100 handleException();
101 }
103 output = strdup(tempPath);
104 free(tempPath);
105 } else {
106 output = strdup(path);
107 }
109 free(path);
110 return output;
111 }
113 //Replaces all occurrences of <find> in <target> with <replace> provided enough <size> is available
114 void LocalCapture::replaceAll(char* target, const char* find, const char* replace, unsigned int size) {
115 char* nextOccurrence;
116 unsigned int count = 0;
118 // Duplicate the original string
119 char* original = strdup(target);
120 char* ptr = original;
122 // Determine number of <find>s
123 ptr = strstr(ptr, find);
124 while (ptr) {
125 count++;
126 ptr += strlen(find);
127 ptr = strstr(ptr, find);
128 }
130 // Is there enough space available
131 if (strlen(target) + (strlen(replace) - strlen(find)) * count > size - 1) {
132 free(original);
133 return;
134 }
136 // Reset
137 ptr = original;
139 nextOccurrence = strstr(ptr, find);
140 while (nextOccurrence) {
141 // Move pointers to location of replace
142 int length = nextOccurrence - ptr;
143 target += length;
144 ptr += length;
146 // Replace <find> with <replace>
147 memcpy(target, replace, strlen(replace));
149 // Increment over <replace>/<find>
150 target += strlen(replace);
151 ptr += strlen(find);
153 // Copy remainder of ptr
154 strcpy(target, ptr);
156 // Get next occurrence
157 nextOccurrence = strstr(ptr, find);
158 }
160 free(original);
161 }
163 int LocalCapture::removeDirAndAllContents(char* path) {
164 int error = 0;
165 struct stat mFileInfo;
166 // Does the path exist?
167 if (stat(path, &mFileInfo) == 0) {
168 // Is it a directory?
169 if (mFileInfo.st_mode & S_IFDIR) {
170 DIR * dir = opendir(path);
171 dirent* entry = readdir(dir);
172 while (entry) {
173 if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
174 char* newpath = (char*)malloc(strlen(path) + strlen(entry->d_name) + 2);
175 sprintf(newpath, "%s/%s", path, entry->d_name);
176 error = removeDirAndAllContents(newpath);
177 free(newpath);
178 if (error) {
179 break;
180 }
181 }
182 entry = readdir(dir);
183 }
184 closedir(dir);
185 if (error == 0) {
186 error = rmdir(path);
187 }
188 } else {
189 error = remove(path);
190 }
191 }
192 return error;
193 }
195 void LocalCapture::copyImages(ImageLinkList* ptr) {
196 char* dstfilename = (char*)malloc(PATH_MAX);
198 while (ptr) {
199 strncpy(dstfilename, gSessionData->mAPCDir, PATH_MAX);
200 dstfilename[PATH_MAX - 1] = 0; // strncpy does not guarantee a null-terminated string
201 if (gSessionData->mAPCDir[strlen(gSessionData->mAPCDir) - 1] != '/') {
202 strncat(dstfilename, "/", PATH_MAX - strlen(dstfilename) - 1);
203 }
204 strncat(dstfilename, util->getFilePart(ptr->path), PATH_MAX - strlen(dstfilename) - 1);
205 if (util->copyFile(ptr->path, dstfilename)) {
206 logg->logMessage("copied file %s to %s", ptr->path, dstfilename);
207 } else {
208 logg->logMessage("copy of file %s to %s failed", ptr->path, dstfilename);
209 }
211 ptr = ptr->next;
212 }
213 free(dstfilename);
214 }