source: trunk/LMDZ.TITAN/libf/muphytitan/csystem.c @ 1849

Last change on this file since 1849 was 1793, checked in by jvatant, 8 years ago

Making Titan's hazy again, part I
+ Added the source folder libf/muphytitan which contains

YAMMS ( Titan's microphysical model ) from J. Burgalat

+ Modif. compilation files linked to this change
JVO

File size: 15.9 KB
Line 
1/* Copyright Jérémie Burgalat (2010-2015)
2 *
3 * burgalat.jeremie@gmail.com
4 *
5 * This software is a computer program whose purpose is to provide configuration
6 * file and command line arguments parsing features to Fortran programs.
7 *
8 * This software is governed by the CeCILL-B license under French law and
9 * abiding by the rules of distribution of free software.  You can  use,
10 * modify and/ or redistribute the software under the terms of the CeCILL-B
11 * license as circulated by CEA, CNRS and INRIA at the following URL
12 * "http://www.cecill.info".
13 *
14 * As a counterpart to the access to the source code and  rights to copy,
15 * modify and redistribute granted by the license, users are provided only
16 * with a limited warranty  and the software's author,  the holder of the
17 * economic rights,  and the successive licensors  have only  limited
18 * liability.
19 *
20 * In this respect, the user's attention is drawn to the risks associated
21 * with loading,  using,  modifying and/or developing or reproducing the
22 * software by the user in light of its specific status of free software,
23 * that may mean  that it is complicated to manipulate,  and  that  also
24 * therefore means  that it is reserved for developers  and  experienced
25 * professionals having in-depth computer knowledge. Users are therefore
26 * encouraged to load and test the software's suitability as regards their
27 * requirements in conditions enabling the security of their systems and/or
28 * data to be ensured and,  more generally, to use and operate it in the
29 * same conditions as regards security.
30 *
31 * The fact that you are presently reading this means that you have had
32 * knowledge of the CeCILL-B license and that you accept its terms.
33 */
34
35#include <errno.h>
36#include <string.h>
37#include <stdlib.h>
38#include <stdio.h>
39#include <limits.h>
40#include <libgen.h>
41#include <sys/param.h>  // MAXPATHLEN
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <sys/ioctl.h>
45#include <pwd.h>
46#include <grp.h>
47#include <dirent.h>
48#include <fcntl.h>
49#include <time.h>
50#include <unistd.h>
51
52#include "csystem.h"
53
54// Hack to get MAXPATHLEN
55#ifndef MAXPATHLEN
56#define MAXPATHLEN 4096
57#endif
58
59/* Get errno */
60int c_get_errno(){
61  int ret = errno;
62  return ret;
63}
64
65/* Get the current working directory */
66char* c_getcwd(){
67  char *tmp;
68  tmp = (char *) malloc((MAXPATHLEN+1)*sizeof(char));
69  memset(tmp,'\0',MAXPATHLEN+1);
70  if (getcwd(tmp,MAXPATHLEN) == NULL) {
71    free(tmp);
72    tmp = NULL;
73  } 
74  return tmp;
75}
76
77
78/* Get the realpath of input path and saves it in output path */ 
79char* c_realpath(const char *input){
80  if (!strlen(input)) {
81    return c_getcwd();
82  }
83  return realpath(input,NULL);
84}
85
86
87/* Get directory name of input path */
88char* c_dirname(const char *in){
89  char *tmp = strdup(in);
90  char *ou = strdup(dirname(tmp));
91  free(tmp);
92  return ou;
93}
94
95/* Get base name of input path */
96char* c_basename(const char *in){
97  char* tmp = strdup(in);
98  char *ou = strdup(basename(tmp));
99  free(tmp);
100  return ou;
101}
102
103/* Get the corresponding name of the given user id */
104char* c_uname(int uid){
105  struct passwd  *pwd;
106  char *name;
107  name = NULL;
108  if ((pwd = getpwuid(uid)) !=  NULL){
109    name = strdup(pwd->pw_name);
110  }
111  return name;
112}
113
114/* Get the corresponding name of the given group id */
115char* c_gname(int gid){
116  struct group *grp;
117  char *name;
118  name = NULL;
119  if ((grp = getgrgid(gid)) != NULL){
120    name = strdup(grp->gr_name);
121  }
122  return name;
123}
124
125/* Get the error message of the given error id */
126char* c_strerror(int err){
127  char *tmp = strdup(strerror(err));
128  if (errno != 0)
129    tmp = "Unknown error\0";
130  return tmp;
131}
132
133
134/* Remove a directory and its contents recursively */
135int c_rmdir_f(const char *path) {
136  DIR *d = opendir(path);
137  size_t path_len = strlen(path);
138  int r = -1;
139  if (d) {
140    struct dirent *p;
141    r = 0;
142    while (!r && (p=readdir(d))) {
143      int r2 = -1;
144      char *buf;
145      size_t len;
146      /* Skip the names "." and ".." as we don't want to recurse on them. */
147      if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) {
148        continue;
149      }
150      len = path_len + strlen(p->d_name) + 2; 
151      buf = malloc(len);
152      if (buf) {
153        struct stat statbuf;
154        snprintf(buf, len, "%s/%s", path, p->d_name);
155        if (!stat(buf, &statbuf)) {
156          if (S_ISDIR(statbuf.st_mode)) {
157            r2 = c_rmdir_f(buf);
158          } else {
159            r2 = unlink(buf);
160          }
161        }
162        free(buf);
163      }
164      r = r2;
165    }
166    closedir(d);
167  }
168  if (!r) {
169    r = rmdir(path);
170        return r?errno:0;
171  }
172  return r;
173}
174
175/* Get some file informations */
176int c_fstat(const char *p, int *pe, int *nl, int *ty, int *ui, int *gi, 
177            long *si, char a[20], char m[20], char c[20]){
178  struct stat stb;
179  struct tm *t;
180  int ret ;
181  //char *tmp;
182  char tmp[20];
183  *pe = *ty = *ui = *gi = *si = -1 ;
184  if (stat(p, &stb) != -1) {
185    *pe = (int)(stb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO));
186    *nl = (int)(stb.st_nlink);
187    if (S_ISREG(stb.st_mode)) *ty = 0 + S_ISLNK(stb.st_mode);
188    else if (S_ISDIR(stb.st_mode)) *ty = 2 + S_ISLNK(stb.st_mode) ;
189    else *ty = 4;
190    *ui = (int)stb.st_uid ; *gi = (int)stb.st_gid ; *si = (long)stb.st_size ;
191    t = localtime(&stb.st_atime) ; ret = strftime(tmp, 20, "%F,%T", t); 
192    if(ret != 0) {strncpy(a,tmp,20); a[19] = '\0';}else{a[0] = '\0';}
193    t = localtime(&stb.st_mtime) ; ret = strftime(tmp, 20, "%F,%T", t);
194    if(ret != 0) {strncpy(m,tmp,20); m[19] = '\0';}else{m[0] = '\0';}
195    t = localtime(&stb.st_ctime) ; ret = strftime(tmp, 20, "%F,%T", t);
196    if(ret != 0) {strncpy(c,tmp,20); c[19] = '\0';}else{c[0] = '\0';}
197    return 0;
198  }
199  return errno;
200}
201
202/* Create a directory or a file in given path */
203int c_create(const char* path, mode_t mode, int astype, int forced){
204  char *p, *d;
205  mode_t perm, cmask;
206  int eval;
207  // we build a directory
208  if (!astype){
209    if(forced){eval=c_mkdirp(path,mode);}else{eval=c_mkdir(path,mode);}
210  }else{
211    // we build a file
212    if (forced){
213      p = strdup(path) ; if(p == NULL) {return errno;}
214      d = dirname(p) ; free(p) ; 
215      if(d == NULL) {return -9;}
216      // we attempts to create parent directory first
217      cmask = umask(0);
218      perm =((S_IRWXU | S_IRWXG | S_IRWXO) & ~(cmask & ~(S_IWUSR | S_IXUSR)));
219      (void)umask(cmask) ;
220      eval = c_mkdirp(d,perm); 
221      if(eval){return eval;}
222    }
223    eval = open(path,O_CREAT|O_EXCL,mode);
224    if (eval == -1) {eval=errno;}else{close(eval);eval=0;}
225  } 
226  return eval ;
227}
228
229/* Change current working directory */
230int c_chdir(const char *path){
231  if (chdir(path) != 0) return errno ;
232  return 0;
233}
234
235/* Remove a directory */
236int c_rmdir(const char *path){
237 if ( rmdir(path) != 0) return errno;
238  return 0;
239}
240
241/* Check if path is accessible */
242int c_access(const char *path, int perm) {
243  int ret;
244  if (perm<0 && perm >7) perm=0;
245  ret = access(path,perm);
246  if (ret) return errno;
247  return 0;
248}
249
250/* Rename a path */
251int c_rename(const char *old, const char *new){
252  if (rename(old,new) != 0) return errno ;
253  return 0;
254}
255
256/* Change path permissions */
257int c_chmod(const char *path, mode_t mode){
258  if (chmod(path,mode) != 0) return errno ;
259  return 0;
260}
261
262/* Create directory */
263int c_mkdir(const char *path, mode_t mode){
264  if(mkdir(path,mode) == 0) {
265    if (chmod(path, mode) == -1) return errno ;
266    return 0;
267  }else{
268    return errno;
269  }
270}
271
272/* Remove file from filesytem */
273int c_remove(const char *path){
274  if (remove(path) != 0) return errno ;
275  return 0;
276}
277
278/* Get terminal size */
279int c_termsize(int *rows,int *cols){
280  struct winsize max;
281  int retval ;
282  retval = ioctl(0, TIOCGWINSZ , &max);
283  if (retval != 0) {
284    retval = errno ;
285    *rows = 20 ; *cols = 80 ;
286  }else{
287    *rows = max.ws_row ;
288    *cols = max.ws_col ;
289  }
290  return retval;
291}
292
293/* Get the current umask (in decimal system) */
294int c_umask(){
295  mode_t mask ;
296  mask = umask(S_IRWXU | S_IRWXG | S_IRWXO); (void) umask(mask) ;
297  return (int)mask;
298}
299
300/* ------------------ THIRD PARTY ------------------ */
301
302/*
303 *  Copyright (c) 1983, 1992, 1993
304 *   The Regents of the University of California.  All rights reserved.
305 *
306 *  Redistribution and use in source and binary forms, with or without
307 *  modification, are permitted provided that the following conditions
308 *  are met:
309 *  1. Redistributions of source code must retain the above copyright
310 *     notice, this list of conditions and the following disclaimer.
311 *  2. Redistributions in binary form must reproduce the above copyright
312 *     notice, this list of conditions and the following disclaimer in the
313 *     documentation and/or other materials provided with the distribution.
314 *  3. All advertising materials mentioning features or use of this software
315 *     must display the following acknowledgement:
316 *   This product includes software developed by the University of
317 *  California, Berkeley and its contributors.
318 *  4. Neither the name of the University nor the names of its contributors
319 *     may be used to endorse or promote products derived from this software
320 *     without specific prior written permission.
321 *
322 *  THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
323 *  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
324 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
325 *  ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
326 *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
327 *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
328 *  OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
329 *  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
330 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
331 *  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
332 *  SUCH DAMAGE.
333 */
334/* Creates directories recursively */
335int c_mkdirp(const char *path, mode_t mode) {
336  struct stat sb;
337  mode_t numask, oumask;
338  int first, last, retval;
339  char *cpath, *p;
340  cpath=strdup(path); if (cpath == NULL) return -1;
341  p = cpath; oumask = 0; retval = 0;
342  if (p[0] == '/') ++p;    /* Skip leading '/'. */
343  for (first = 1, last = 0; !last ; ++p) {
344    if (p[0] == '\0') last = 1;
345    else if (p[0] != '/') continue;
346    *p = '\0';
347    //if (! strlen(p) && p[1] == '\0') last = 1;
348    if (first) {
349      oumask = umask(0);
350      numask = oumask & ~(S_IWUSR | S_IXUSR);
351      (void)umask(numask);
352      first = 0;
353    }
354    if (last) (void)umask(oumask);
355    if (mkdir(cpath, last ? mode : S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
356      if (errno == EEXIST || errno == EISDIR) {
357        if (stat(cpath, &sb) < 0) {
358          retval = 1; break;
359        } else if (!S_ISDIR(sb.st_mode)) {
360          if (last) errno = EEXIST; else errno = ENOTDIR;
361          retval = 1; break;
362        }
363      } else {
364        retval = 1; break;
365      }
366    } 
367    if (!last) *p = '/';
368  }
369  if (!first && !last) (void)umask(oumask);
370  if (!retval){
371    if (chmod(path, mode) == -1)  retval = errno ;
372  } else {
373   retval = errno;
374  }
375  free(cpath);
376  return retval ;
377}
378
379/*
380 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
381 *
382 * @APPLE_LICENSE_HEADER_START@
383 *
384 * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
385 * Reserved.  This file contains Original Code and/or Modifications of
386 * Original Code as defined in and that are subject to the Apple Public
387 * Source License Version 1.0 (the 'License').  You may not use this file
388 * except in compliance with the License.  Please obtain a copy of the
389 * License at http://www.apple.com/publicsource and read it before using
390 * this file.
391 *
392 * The Original Code and all software distributed under the License are
393 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
394 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
395 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
396 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
397 * License for the specific language governing rights and limitations
398 * under the License."
399 *
400 * @APPLE_LICENSE_HEADER_END@
401 *
402 * Modified version: J. Burgalat (2015)
403 *
404 */
405
406char* c_relpath(const char *path, const char *reldir) {
407  char start_path[MAXPATHLEN+1];
408  char end_path[MAXPATHLEN+1];
409  char *buf;
410  struct stat st;
411  int i,mc;
412  int last_elem;
413  int prev_path;
414  char *tmp,*cur;
415  buf = NULL;
416
417  if (realpath(reldir,start_path) == NULL) 
418    return buf;
419 
420  if (realpath(path,end_path) == NULL) 
421    return buf;
422
423  // stat the starting path
424  if (stat(start_path, &st) < 0) 
425    return buf;
426 
427  if ((st.st_mode & S_IFMT) != S_IFDIR) {
428    errno = ENOTDIR;
429    return buf;
430  } 
431  if (start_path[strlen(start_path) - 1] != '/')
432    strcat(start_path, "/");
433
434  // stat the ending path path
435  if (stat(end_path, &st) < 0) 
436    return buf;
437 
438  if ((st.st_mode & S_IFMT) == S_IFDIR
439      && end_path[strlen(end_path) - 1] != '/')
440    strcat(end_path, "/");
441
442  tmp = (char *) malloc((2*MAXPATHLEN+1)*sizeof(char));
443  memset(tmp,'\0',2*MAXPATHLEN+1);
444  cur = tmp;
445  /* strip common prefix */
446  i = 0;
447  last_elem = 0;
448  while (start_path[i] && start_path[i] == end_path[i]) {
449    if (start_path[i] == '/')
450      last_elem = i + 1;
451    i += 1;
452  }
453  prev_path = 0;
454  for (i = last_elem; start_path[i]; i += 1) {
455    if (start_path[i] == '/') {
456      if (prev_path){
457        *cur = '/'; cur++;
458      }
459      strncpy(cur,"..",2) ; cur +=2;
460      prev_path = 1;
461    }
462  }
463  if (end_path[last_elem]) {
464    if (prev_path) {
465      *cur = '/'; cur++;
466    }
467    prev_path = 1;
468    while (end_path[strlen(end_path) - 1] == '/')
469      end_path[strlen(end_path) - 1] = '\0';
470    strcpy(cur,&end_path[last_elem]) ;
471    cur += strlen(&end_path[last_elem]);
472  }
473  if (! prev_path){
474    *cur = '.' ; cur++ ;
475  }
476  // Normally here tmp contains our path. We just need to copy it in buf
477  mc = strlen(tmp)+1;
478  buf = (char *)malloc(mc*sizeof(char));
479  memset(buf,'\0',mc);
480  strncpy(buf,tmp,strlen(tmp));
481  cur = buf;
482  i=0;
483  while (*cur != '\0' && i < mc){
484    cur++;
485    i++;
486  }
487  free(tmp);
488  errno = 0;
489  return buf;
490}
491
492/* This verison of realpath was a dumb attempt to get a resolved path
493 * that may not exist. As a matter of fact, it cannot cover all range
494 * of possibilities.
495 * Thus it has been removed. The current verison of c_realpath simply
496 * uses POSIX realpath and returns CWD if no path is given...
497 */
498
499/* Get the realpath of input path and saves it in output path */ 
500/*
501char* c_realpath(const char *input){
502  char *in,*output, *cur,*tmp,*res,*cwd ;
503  int c,om,rm,im;
504  output = NULL;
505  cwd = c_getcwd();
506  if(!strlen(input))
507    return cwd;
508  // check (ugly) if path is absolute
509  if (input[0] == '/') {
510    in = strdup(input);
511  }else{
512    fprintf(stderr,"+++ C( in): %s\n",input);
513    in = malloc((strlen(input)+strlen(cwd)+2)*sizeof(char));
514    strncpy(in, cwd, strlen(cwd));
515    strncpy(&in[strlen(cwd)+1], input, strlen(input));
516    in[strlen(cwd)] = '/';
517    in[strlen(input)+strlen(cwd)+1] = '\0';
518  }
519  fprintf(stderr,"C( in): %s\n",in);
520  c = om = im = strlen(in);
521  tmp = malloc((c+1)*sizeof(char));
522  tmp[c] ='\0';
523  // search for the deepest existing directory in "input" path
524  while(c != 0 && (res = realpath(tmp,NULL)) == NULL){
525    // search for the next / from the right (i.e. parent directory)
526    for (cur=tmp+strlen(tmp) ; *cur != '/' && cur != tmp ; cur--, c--);
527    free(tmp) ; tmp = malloc((c+1)*sizeof(char));
528    strncpy(tmp, in, c); tmp[c] ='\0';
529  }
530  free(tmp);
531  // On error: null string
532  if (c == 0 || (res==NULL)) {
533    output = (char *)malloc(sizeof(char));
534    output[0]='\0';
535    return output;
536  }
537  // no error: allocate output string
538  rm = strlen(res);
539  om += rm-c;
540  output = (char *)malloc(om*sizeof(char));
541  strncpy(output,res,rm);
542  // Here we could have a bug:
543  //    If the path does not exist and contains .. or . references after the deepest
544  //    existing directory, it will simply be appended !
545  //    Thus we can never resolve the path.
546  if (c != im)
547    strncpy(output+rm,in+c,im-c);
548    //strncpy(output+rm,in+c,im-c-1);
549  output[om] = '\0';
550  fprintf(stderr,"C(tmp): %s\n",res);
551  fprintf(stderr,"C(out): %s\n",output);
552  free(res) ;
553  return output;
554}
555*/
Note: See TracBrowser for help on using the repository browser.