SURFEX v8.1
General documentation of Surfex
lfi_util.c
Go to the documentation of this file.
1 /**** *lfi_util.c* - Ancillary routines
2  *
3  * Author.
4  * -------
5  * Philippe Marguinaud *METEO-FRANCE*
6  * Original : 12-08-2013
7  *
8  */
9 #include <stdlib.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <errno.h>
13 #include <sys/stat.h>
14 #include <sys/types.h>
15 #include <unistd.h>
16 
17 #include "lfi_util.h"
18 
19 /* Compute the length of a Fortran character string */
21 {
23  for (i = len; i > 0; i--)
24  if (fstr[i-1] != ' ')
25  break;
26  return i;
27 }
28 
29 /* Makes a C character string out of a Fortran string */
30 char * lfi_fstrdup (const character * fstr, const character_len len, char * cstr)
31 {
32  int i;
33 
34  if (cstr == NULL)
35  cstr = (char *)malloc (len + 1);
36 
37  memcpy (cstr, fstr, len);
38  cstr[len] = '\0';
39 
40  for (i = len-1; i >= 0; i--)
41  if (fstr[i] == ' ')
42  cstr[i] = '\0';
43  else
44  break;
45 
46  return cstr;
47 }
48 
49 int lfi_fstrcmp (const character * s1, const character * s2, character_len len1, character_len len2)
50 {
51  int i;
52  len1 = lfi_fstrlen (s1, len1);
53  len2 = lfi_fstrlen (s2, len2);
54  if (len1 > len2)
55  return +1;
56  if (len1 < len2)
57  return -1;
58  for (i = 0; i < len1; i++)
59  if (s1[i] > s2[i])
60  return +1;
61  if (s1[i] < s2[i])
62  return -1;
63  return 0;
64 }
65 
66 char * lfi_fdirname (const character * fstr, const character_len len)
67 {
68  char * dir;
69  int i;
70 
71  for (i = len; i > 0; i--)
72  if (fstr[i-1] == '/')
73  break;
74 
75  dir = (char *)malloc (i + 1);
76 
77  strncpy (dir, fstr, i);
78  dir[i] = '\0';
79 
80  return dir;
81 }
82 
83 int lfi_copy (const char * f1, const char * f2)
84 {
85 #define SIZE 4096
86  char buf[SIZE];
87  FILE * fp1;
88  FILE * fp2;
89  int nr;
90 
91  errno = 0;
92 
93  if ((fp1 = fopen (f1, "r")) == NULL)
94  goto error;
95 
96  if ((fp2 = fopen (f2, "w")) == NULL)
97  goto error;
98 
99  while ((nr = fread (buf, 1, SIZE, fp1)) > 0)
100  {
101  if (fwrite (buf, 1, SIZE, fp2) != nr)
102  goto error;
103 
104  if (nr < SIZE)
105  break;
106  }
107 
108  if (ferror (fp1))
109  goto error;
110 
111 
112 #undef SIZE
113 
114  if (fclose (fp1) != 0)
115  goto error;
116  if (fclose (fp2) != 0)
117  goto error;
118 
119 
120 error:
121 
122  return errno;
123 }
124 
125 int lfi_fcopy (const character * cnomf1, const character * cnomf2, character_len cnomf1_len, character_len cnomf2_len)
126 {
127  char f1[cnomf1_len+1];
128  char f2[cnomf2_len+1];
129  return lfi_copy (lfi_fstrdup (cnomf1, cnomf1_len, f1), lfi_fstrdup (cnomf2, cnomf2_len, f2));
130 }
131 
132 int lfi_fsmartcopy (const character * cnomf1, const character * cnomf2, int copy,
133  character_len cnomf1_len, character_len cnomf2_len)
134 {
135  char f1[cnomf1_len+1];
136  char f2[cnomf2_len+1];
137  return lfi_smartcopy (lfi_fstrdup (cnomf1, cnomf1_len, f1), lfi_fstrdup (cnomf2, cnomf2_len, f2), copy);
138 }
139 
140 int lfi_smartcopy (const char * f1, const char * f2, int copy)
141 {
142  int c = 0;
143 
144  errno = 0;
145 
146  if (link (f1, f2) != 0)
147  {
148  if ((errno == EXDEV) && copy)
149  c = lfi_copy (f1, f2);
150  else
151  c = errno;
152  }
153 
154  return c;
155 }
156 
157 int lfi_mkdir (const char * path)
158 {
159  struct stat st;
160 
161  if (stat (path, &st) == 0)
162  return 0;
163 
164  errno = 0;
165 
166  return mkdir (path, 0777);
167 }
168 
169 const char * lfi_cleanup_path (char * path)
170 {
171  int i, j;
172 
173  /* Cleanup; remove double / */
174 
175  for (i = 0; path[i]; )
176  if ((path[i] == '/') && (path[i+1] == '/'))
177  strcpy (&path[i], &path[i+1]);
178  else
179  i++;
180 
181  /* Cleanup path (collapse '/dir/../' in '/') */
182 
183 again:
184  for (i = 0, j = 0; path[i]; i++)
185  if (strncmp (&path[i], "/../", 3) == 0)
186  {
187  if (j > 0)
188  {
189  strcpy (&path[j], &path[i+4]);
190  goto again;
191  }
192  }
193  else if (path[i] == '/')
194  {
195  j = i + 1;
196  }
197 
198  return path;
199 }
200 
201 /*
202  * Example : (base = "/home/marguina/tmp/ICMSH0000+0000",
203  * path = "/home/marguina/tmp/ICMSH0000+0000.d/0000")
204  * returns "ICMSH0000+0000.d/0000"
205  */
206 
207 char * lfi_make_relative_path (const char * base, char * path)
208 {
209  char * _base_ = strdup (base);
210  char * _path_ = strdup (path);
211  char * _base = _base_;
212  char * _path = _path_;
213  int i, j, k;
214 
215  lfi_cleanup_path (_base);
216  lfi_cleanup_path (_path);
217 
218  /* Find out common _path in __path and __base */
219 
220  for (i = 0, j = 0, k = 0; _base[i] && _path[i]; i++)
221  if (_base[i] != _path[i])
222  {
223  break;
224  }
225  else if (_base[i] == '/')
226  {
227  j = i + 1;
228  k++;
229  }
230 
231  /* Remove common part and truncate _base */
232 
233  _base = &_base[j];
234  _path = &_path[j];
235 
236  for (i = strlen (_base); i > 0; i--)
237  if (_base[i] == '/')
238  break;
239 
240  _base[i] = '\0';
241 
242  /* Depth count */
243 
244  if (_base[0])
245  j = 1;
246  else
247  j = 0;
248 
249  for (i = 0; _base[i]; i++)
250  if (_base[i] == '/')
251  j++;
252 
253  free ((void *)path);
254  path = (char *)malloc (3 * j + strlen (_path) + 1);
255  path[0] = '\0';
256 
257  /* Build final path */
258 
259  while (j--)
260  strcat (path, "../");
261 
262  strcat (path, _path);
263 
264  free ((void *)_base_);
265  free ((void *)_path_);
266 
267  lfi_cleanup_path (path);
268 
269  return path;
270 }
271 
272 int lfi_rmdir (const char * path)
273 {
274  errno = 0;
275  return rmdir (path);
276 }
277 
278 const char * lfi_dirname (const char * path)
279 {
280  int i;
281  char * dir = strdup (path);
282 
283  for (i = strlen (dir); i >= 0; i--)
284  if (dir[i] == '/')
285  {
286  dir[i] = '\0';
287  return (const char *)dir;
288  }
289 
290  strcpy (dir, ".");
291 
292  return dir;
293 }
294 
295 
int lfi_mkdir(const char *path)
Definition: lfi_util.c:157
char * lfi_fdirname(const character *fstr, const character_len len)
Definition: lfi_util.c:66
char * lfi_fstrdup(const character *fstr, const character_len len, char *cstr)
Definition: lfi_util.c:30
int lfi_smartcopy(const char *f1, const char *f2, int copy)
Definition: lfi_util.c:140
const char * lfi_dirname(const char *path)
Definition: lfi_util.c:278
int character_len
Definition: lfi_type.h:17
char character
Definition: lfi_type.h:18
char * lfi_make_relative_path(const char *base, char *path)
Definition: lfi_util.c:207
character_len lfi_fstrlen(const character *fstr, const character_len len)
Definition: lfi_util.c:20
int lfi_fcopy(const character *cnomf1, const character *cnomf2, character_len cnomf1_len, character_len cnomf2_len)
Definition: lfi_util.c:125
const char * lfi_cleanup_path(char *path)
Definition: lfi_util.c:169
int lfi_copy(const char *f1, const char *f2)
Definition: lfi_util.c:83
int lfi_fstrcmp(const character *s1, const character *s2, character_len len1, character_len len2)
Definition: lfi_util.c:49
int lfi_fsmartcopy(const character *cnomf1, const character *cnomf2, int copy, character_len cnomf1_len, character_len cnomf2_len)
Definition: lfi_util.c:132
int lfi_rmdir(const char *path)
Definition: lfi_util.c:272