Upstream tarball 20080721
[amule.git] / src / utils / cas / functions.c
blobd5e3dda252534355560e7d955b59e6c688bdfeb2
1 /*
2 * Name: Shared functions
4 * Purpose: Functions that are used various times in cas
6 * Author: Pedro de Oliveira <falso@rdk.homeip.net>
8 * Copyright (c) 2004-2008 Pedro de Oliveira
9 *
10 * This file is part of aMule.
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the
24 * Free Software Foundation, Inc.,
25 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <errno.h>
34 /* XXX This needs to be replaced so that we use
35 * autoconf to detect the target OS -- As of now
36 * it should compile fine in other non UNIX-like
37 * platforms, at the expense of only being sure
38 * that UNIX-specific code will be compiled if
39 * using GCC (which defines those __unix__ macros)
40 * autoconf defines should be in place to test for
41 * functions like getpwuid() in UNIX-like systems
42 * instead of doing this...
45 #ifdef __APPLE__
46 #include <CoreServices/CoreServices.h>
47 #define CAS_DIR_SEPARATOR "/"
48 #elif defined(__WIN32__)
49 #define COBJMACROS
50 #include <winerror.h>
51 #include <shlobj.h>
52 #include <objidl.h>
53 #define CAS_DIR_SEPARATOR "\\"
54 #else
55 #define CAS_DIR_SEPARATOR "/"
56 #if defined(unix) || defined(__unix__) || defined(__unix)
57 #include <unistd.h>
58 #include <pwd.h>
59 #include <fcntl.h>
60 #define CAS_UNIX
61 #endif
62 #endif
64 /* try (hard) to get correct path for aMule signature
65 * !! it's caller's responsibility to free return value
68 char *get_path(const char *file)
70 char *ret; /* caller should free return value */
71 static char *saved_home = NULL;
72 static size_t home_len = 0;
74 if (saved_home == NULL) {
75 #ifdef __APPLE__
77 char home[PATH_MAX];
78 home[0] = '\0';
80 FSRef fsRef;
81 if (FSFindFolder(kUserDomain, kApplicationSupportFolderType, kCreateFolder, &fsRef) == noErr) {
82 CFURLRef urlRef = CFURLCreateFromFSRef(NULL, &fsRef);
83 if (urlRef != NULL) {
84 if (CFURLGetFileSystemRepresentation(urlRef, true, home, sizeof(home))) {
85 strcat(home, CAS_DIR_SEPARATOR "aMule");
87 CFRelease(urlRef) ;
91 #elif defined(__WIN32__)
93 LPITEMIDLIST pidl;
94 char home[MAX_PATH];
95 home[0] = '\0';
97 HRESULT hr = SHGetSpecialFolderLocation(NULL, CSIDL_APPDATA, &pidl);
99 if (SUCCEEDED(hr)) {
100 if (SHGetPathFromIDList(pidl, home)) {
101 strcat(home, CAS_DIR_SEPARATOR "aMule");
105 if (pidl) {
106 LPMALLOC pMalloc;
107 SHGetMalloc(&pMalloc);
108 if (pMalloc) {
109 IMalloc_Free(pMalloc, pidl);
110 IMalloc_Release(pMalloc);
115 #else
116 char *home;
118 /* get home directory */
119 if ( (home = getenv("HOME")) == NULL) {
120 #ifndef CAS_UNIX
121 return NULL;
122 #else
123 /* if $HOME is not available try user database */
124 uid_t uid;
125 struct passwd *pwd;
127 uid = getuid();
128 pwd = getpwuid(uid);
129 endpwent();
131 /* XXX
132 * Section 6.5.14 of ANSI C specs (grab C99 at http://www.nirvani.net/docs/ansi_c.pdf)
133 * states this:
134 * "Unlike the bitwise | operator, the || operator _guarantees_ left-to-right
135 * evaluation; there is a sequence point after the evaluation of the first
136 * operand. If the first operand compares unequal to 0, the second operand
137 * _is not evaluated_."
139 * I'm going to revert it and wait until Jacobo or whoever changed it
140 * screams loudly, tries to kill me, and explains why this has to be
141 * this way. Maybe pre-ansi compilers? Doubtful.
143 * - Unleashed
145 if (pwd == NULL || pwd->pw_dir == NULL)
146 return NULL;
148 home = pwd->pw_dir;
149 #endif /* CAS_UNIX */
151 strcat(home, CAS_DIR_SEPARATOR ".aMule");
153 #endif /* !__APPLE__ && !__WIN32__ */
155 /* save the result for future calls */
156 home_len = strlen(home);
157 if ( (saved_home = strdup(home)) == NULL)
158 return NULL;
161 /* get full path space */
163 /* Unleashed - Guys... you broke this and it was OK
164 * "+ 2" means "plus '/' and '\0'"
166 ret = malloc((home_len + strlen(file) + 2) * sizeof(char));
167 if (ret == NULL)
168 return NULL;
170 strcpy(ret, saved_home);
171 ret[home_len] = CAS_DIR_SEPARATOR[0];
172 ret[home_len+1] = '\0';
173 strcat(ret, file);
174 /* the string is guaranteed to be null-terminated
175 * so no need to do this...
176 * ret[total_len] = '\0';
179 return ret;
182 char *get_amule_path(const char *file, int force_directory, const char *cmdline_path)
184 char *path;
186 if (!cmdline_path) {
187 return get_path(file);
190 if ((path = malloc(strlen(cmdline_path) + strlen(file) + 2)) == NULL) {
191 return NULL;
194 strcpy(path, cmdline_path);
195 if (force_directory) {
196 if (path[strlen(path) - 1] != CAS_DIR_SEPARATOR[0]) {
197 strcat(path, CAS_DIR_SEPARATOR);
199 strcat(path, file);
200 } else {
201 if (path[strlen(path) - 1] == CAS_DIR_SEPARATOR[0]) {
202 strcat(path, file);
206 return path;
210 * this function is used to convert bytes to any other unit
211 * nicer to the eye.
213 * return "Bad format" if could not convert string
215 char *convbytes(char *input)
217 char *units[] = { "Bytes", "KB", "MB", "GB", "TB", "PB" };
218 char *endptr;
219 static char output[50];
220 float bytes;
221 unsigned int i = 0;
223 /* do proper conversion and check for errors */
224 errno = 0;
225 bytes = (float) strtod(input, &endptr);
227 /* check bad string conversion or value out of range */
228 if (*endptr != '\0' || errno == ERANGE)
229 return "Bad format";
231 /* this loop converts bytes and sets i to the appropriate
232 * index in 'units' array
233 * note: sizeof(units) / sizeof(char*) is the number of
234 * elements in 'units' array
236 for (; i < (sizeof(units) / sizeof(char *)) - 1; i++) {
237 if (bytes < 1024)
238 break;
239 bytes /= 1024;
242 snprintf(output, 50, "%.2f %s", bytes, units[i]);
244 return output;
247 void replace(char *tmpl, const char *search, const char *to_replace)
249 char *dest = NULL;
250 char *retStr = NULL;
251 int befLen,srchLen,repLen,totLen;
253 /* returning the 'tmpl' if 'search' is NULL */
254 if (NULL == tmpl || NULL == search) /* || NULL == to_replace) */
256 return;
259 while (1)
261 /* if 'search' is found in 'tmpl' */
262 retStr = strstr(tmpl, search);
263 if (NULL == retStr)
265 return;
268 totLen = strlen(tmpl);
269 befLen = (int)(retStr - tmpl);
270 srchLen = strlen(search);
271 repLen = strlen(to_replace);
273 /* dynamic buffer creation... */
274 dest = (char*)malloc(totLen + 1 + repLen - srchLen);
275 if (NULL == dest)
276 return;
278 /* copy the before buffer */
279 strncpy(dest, tmpl, befLen);
280 /* copy the replace string */
281 memcpy((dest+befLen), to_replace, repLen); /* strcat(dest, to_replace); */
282 /* copy the after buffer */
283 memcpy((dest+befLen+repLen), &tmpl[befLen + srchLen], strlen(&tmpl[befLen + srchLen])); /*strcat(dest, &tmpl[befLen + repLen]); */
285 /* now replace the template string with the resulting and search it again */
286 strcpy(tmpl, dest);
287 /* we need this, because we're modifying the 'tmpl' instead of creating a new one (so we need to update the position of the null char) */
288 tmpl[totLen - srchLen + repLen] = '\0';
289 /* clean up... */
290 free(dest);
294 char *timeconv(char *input)
296 int count = atoi(input);
297 static char ret[50];
299 if (count < 0)
300 snprintf (ret,50,"?");
301 else if (count < 60)
302 snprintf (ret,50,"%02i %s", count, "secs" );
303 else if (count < 3600)
304 snprintf (ret,50,"%i:%02i %s", count/60, (count % 60), "mins" );
305 else if (count < 86400)
306 snprintf (ret,50,"%i:%02i %s", count/3600, (count % 3600)/60, "h" );
307 else
308 snprintf (ret,50,"%i %s %02i %s", count/86400, "D" , (count % 86400) / 3600, "h" );
310 return (ret);