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->apcDir = createUniqueDirectory(target_path, ".apc", name);
28 if ((removeDirAndAllContents(gSessionData->apcDir) != 0 || mkdir(gSessionData->apcDir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0)) {
29 logg->logError(__FILE__, __LINE__, "Unable to create directory %s", gSessionData->apcDir);
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->apcDir);
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 strncat(path, "/@F_@N", PATH_MAX - strlen(path) - 1);
59 } else if (initialPath[0] != '/') {
60 if (getcwd(path, PATH_MAX) == 0)
61 logg->logMessage("Unable to retrive the current working directory");
62 strncat(path, "/", PATH_MAX - strlen(path) - 1);
63 strncat(path, initialPath, PATH_MAX - strlen(path) - 1);
64 } else {
65 strncpy(path, initialPath, PATH_MAX);
66 path[PATH_MAX - 1] = 0; // strncpy does not guarantee a null-terminated string
67 }
69 // Convert to uppercase
70 replaceAll(path, "@f", "@F", PATH_MAX);
71 replaceAll(path, "@n", "@N", PATH_MAX);
73 // Replace @F with the session xml title
74 replaceAll(path, "@F", title, PATH_MAX);
76 // Add ending if it is not already there
77 if (strcmp(&path[strlen(path) - strlen(ending)], ending) != 0) {
78 strncat(path, ending, PATH_MAX - strlen(path) - 1);
79 }
81 // Replace @N with a unique integer
82 if (strstr(path, "@N")) {
83 char* tempPath = (char*)malloc(PATH_MAX);
84 for (i = 1; i < 1000; i++) {
85 char number[4];
86 snprintf(number, sizeof(number), "%03d", i);
87 strcpy(tempPath, path);
88 replaceAll(tempPath, "@N", number, PATH_MAX);
89 struct stat mFileInfo;
90 if (stat(tempPath, &mFileInfo) != 0) {
91 // if the direcotry does not exist, break
92 break;
93 }
94 }
96 if (i == 1000) {
97 logg->logError(__FILE__, __LINE__, "Unable to create .apc directory, please delete older directories.");
98 handleException();
99 }
101 output = strdup(tempPath);
102 free(tempPath);
103 } else {
104 output = strdup(path);
105 }
107 free(path);
108 return output;
109 }
111 //Replaces all occurrences of <find> in <target> with <replace> provided enough <size> is available
112 void LocalCapture::replaceAll(char* target, const char* find, const char* replace, unsigned int size) {
113 char* nextOccurrence;
114 unsigned int count = 0;
116 // Duplicate the original string
117 char* original = strdup(target);
118 char* ptr = original;
120 // Determine number of <find>s
121 ptr = strstr(ptr, find);
122 while (ptr) {
123 count++;
124 ptr += strlen(find);
125 ptr = strstr(ptr, find);
126 }
128 // Is there enough space available
129 if (strlen(target) + (strlen(replace) - strlen(find)) * count > size - 1) {
130 free(original);
131 return;
132 }
134 // Reset
135 ptr = original;
137 nextOccurrence = strstr(ptr, find);
138 while (nextOccurrence) {
139 // Move pointers to location of replace
140 int length = nextOccurrence - ptr;
141 target += length;
142 ptr += length;
144 // Replace <find> with <replace>
145 memcpy(target, replace, strlen(replace));
147 // Increment over <replace>/<find>
148 target += strlen(replace);
149 ptr += strlen(find);
151 // Copy remainder of ptr
152 strcpy(target, ptr);
154 // Get next occurrence
155 nextOccurrence = strstr(ptr, find);
156 }
158 free(original);
159 }
161 int LocalCapture::removeDirAndAllContents(char *path) {
162 int error = 0;
163 struct stat mFileInfo;
164 // Does the path exist?
165 if (stat(path, &mFileInfo) == 0) {
166 // Is it a directory?
167 if (mFileInfo.st_mode & S_IFDIR) {
168 DIR * dir = opendir(path);
169 dirent* entry = readdir(dir);
170 while (entry) {
171 if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
172 char* newpath = (char*)malloc(strlen(path) + strlen(entry->d_name) + 2);
173 sprintf(newpath, "%s/%s", path, entry->d_name);
174 error = removeDirAndAllContents(newpath);
175 free(newpath);
176 if (error) break;
177 }
178 entry = readdir(dir);
179 }
180 closedir(dir);
181 if (error == 0) {
182 error = rmdir(path);
183 }
184 } else {
185 error = remove(path);
186 }
187 }
188 return error;
189 }
191 void LocalCapture::copyImages(ImageLinkList* ptr) {
192 char* dstfilename = (char*)malloc(PATH_MAX);
194 while (ptr) {
195 strncpy(dstfilename, gSessionData->apcDir, PATH_MAX);
196 dstfilename[PATH_MAX - 1] = 0; // strncpy does not guarantee a null-terminated string
197 if (gSessionData->apcDir[strlen(gSessionData->apcDir) - 1] != '/')
198 strncat(dstfilename, "/", PATH_MAX - strlen(dstfilename) - 1);
199 strncat(dstfilename, util->getFilePart(ptr->path), PATH_MAX - strlen(dstfilename) - 1);
200 if (util->copyFile(ptr->path, dstfilename))
201 logg->logMessage("copied file %s to %s", ptr->path, dstfilename);
202 else
203 logg->logMessage("copy of file %s to %s failed", ptr->path, dstfilename);
205 ptr = ptr->next;
206 }
207 free(dstfilename);
208 }