source: trunk/drmaa_utils/drmaa_utils/fsd_util.c @ 1

Revision 1, 11.6 KB checked in by mmamonski, 13 years ago (diff)

Torque/PBS DRMAA initial commit

Line 
1/* $Id: fsd_util.c 185 2010-05-13 17:10:00Z mmatloka $ */
2/*
3 *  FedStage DRMAA utilities library
4 *  Copyright (C) 2006-2008  FedStage Systems
5 *
6 *  This program is free software: you can redistribute it and/or modify
7 *  it under the terms of the GNU General Public License as published by
8 *  the Free Software Foundation, either version 3 of the License, or
9 *  (at your option) any later version.
10 *
11 *  This program is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *  GNU General Public License for more details.
15 *
16 *  You should have received a copy of the GNU General Public License
17 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#ifdef HAVE_CONFIG_H
21#       include <config.h>
22#endif
23
24#include <fcntl.h>
25#include <sys/stat.h>
26#include <sys/time.h>
27#include <unistd.h>
28
29#include <ctype.h>
30#include <errno.h>
31#include <limits.h>
32#include <signal.h>
33#include <stdlib.h>
34#include <string.h>
35#include <stdio.h>
36
37#include <drmaa_utils/common.h>
38#include <drmaa_utils/util.h>
39
40#ifndef lint
41static char rcsid[]
42#       ifdef __GNUC__
43                __attribute__ ((unused))
44#       endif
45        = "$Id: fsd_util.c 185 2010-05-13 17:10:00Z mmatloka $";
46#endif
47
48
49static char *
50fsd_expand_printf_ph( const char *fmt );
51
52
53void
54fsd_free_vector( char **vector )
55{
56        char **i;
57        if( vector == NULL )
58                return;
59        for( i = vector;  *i != NULL;  i++ )
60                fsd_free( *i );
61        fsd_free( vector );
62}
63
64
65char **
66fsd_copy_vector( const char *const * vector )
67{
68        unsigned n_items, i;
69        char** volatile buf = NULL;
70        char** volatile result = NULL;
71
72        TRY
73         {
74                if( vector )
75                        for( n_items = 0;  vector[ n_items ] != NULL;  n_items++ ) {}
76                else
77                        n_items = 0;
78
79                fsd_calloc( buf, n_items+1, char* );
80                for( i = 0;  i < n_items;  i++ )
81                        buf[i] = fsd_strdup( vector[i] );
82         }
83        ELSE
84         { result = buf;  buf = NULL; }
85        FINALLY
86         { fsd_free_vector( buf ); }
87        END_TRY
88
89        return result;
90}
91
92
93char *
94fsd_replace( char *str, const char *placeholder, const char *value )
95{
96        size_t ph_len, v_len;
97        char *found = NULL;
98        char* volatile s = str;
99
100        if( str == NULL )
101                fsd_exc_raise_code( FSD_ERRNO_INTERNAL_ERROR );
102
103        ph_len = strlen( placeholder );
104        v_len  = strlen( value );
105
106        do {
107                size_t s_len;
108                s_len = strlen( s );
109                found = strstr( s, placeholder );
110                if( found )
111                 {
112                        char* volatile result;
113                        size_t pos = found - s;
114                        TRY
115                         {
116                                fsd_calloc( result, s_len - ph_len + v_len + 1, char );
117                                memcpy( result, s, pos );
118                                memcpy( result+pos, value, v_len );
119                                memcpy( result+pos+v_len, s+pos+ph_len, s_len-pos-ph_len );
120                                result[ s_len-ph_len+v_len ] = 0;
121                         }
122                        FINALLY
123                         {
124                                fsd_free( s );
125                                s = result;
126                         }
127                        END_TRY
128                 }
129        } while( found );
130
131        return s;
132}
133
134
135char *
136fsd_explode( const char *const *vector, char glue, int n )
137{
138        char* volatile result = NULL;
139        char* volatile buf = NULL;
140        char *s;
141        const char *const *i;
142        unsigned idx, max=(unsigned)n;
143        size_t size =0;
144
145        TRY
146         {
147                for( i = vector, idx = 0;  idx < max && *i != NULL;  i++, idx++ )
148                 {
149                        if( i != vector )
150                                size++;
151                        size += strlen(*i);
152                 }
153
154                fsd_calloc( buf, size+1, char );
155                s = buf;
156                for( i = vector, idx = 0;  idx < max && *i != NULL;  i++, idx++ )
157                 {
158                        if( i != vector )
159                                *s++ = glue;
160                        strcpy( s, *i );
161                        s += strlen( *i );
162                 }
163         }
164        ELSE
165         { result = buf;  buf = NULL; }
166        FINALLY
167         { fsd_free( buf ); }
168        END_TRY
169
170        return result;
171}
172
173
174char *
175fsd_strdup( const char *s )
176{
177        char *result;
178        if( s == NULL )
179                return NULL;
180        result = strdup( s );
181        if( result == NULL )
182                fsd_exc_raise_sys( ENOMEM );
183        return result;
184}
185
186
187char *
188fsd_strndup( const char *s, size_t n )
189{
190        char *result;
191        if( s == NULL )
192                return NULL;
193        result = strndup( s, n );
194        if( result == NULL )
195                fsd_exc_raise_sys( ENOMEM );
196        return result;
197}
198
199
200int
201fsd_atoi( const char *string )
202{
203        const char *s = string;
204        int sign = +1;
205        int v = 0;
206
207        while( isspace(*(const unsigned char*)s) )
208                s++;
209        switch( *s )
210         {
211                case '+':  sign = +1;  s++;  break;
212                case '-':  sign = -1;  s++;  break;
213                default:  break;
214         }
215        while( isspace(*(const unsigned char*)s) )
216                s++;
217        if( '0' <= *s  &&  *s <= '9' )
218         {
219                while( '0' <= *s  &&  *s <= '9' )
220                 {
221                        if( v > INT_MAX/10 )
222                                goto range_error;
223                        v *= 10;
224                        v += *s++ - '0';
225                        if( v < 0 )
226                                goto range_error;
227                 }
228         }
229        else
230                goto nan_error;
231
232        while( isspace(*(const unsigned char*)s) )
233                s++;
234        if( *s != '\0' )
235                goto nan_error;
236
237        return sign * v;
238
239range_error:
240        fsd_exc_raise_fmt( FSD_ERRNO_INVALID_ARGUMENT,
241                        "value out of range: %s", string );
242        return 0;
243
244nan_error:
245                fsd_exc_raise_fmt( FSD_ERRNO_INVALID_ARGUMENT,
246                                "not an number: %s", string );
247        return 0;
248}
249
250
251void
252fsd_str_append(
253                bool *truncated,
254                char **p, char *end,
255                const char *fmt, ...
256                )
257{
258        va_list args;
259        va_start( args, fmt );
260        *p += fsd_vsnprintf( truncated, *p, end-*p, fmt, args );
261        va_end( args );
262}
263
264
265size_t
266fsd_snprintf(
267                bool *truncated,
268                char *str, size_t size,
269                const char *fmt, ...
270                )
271{
272        va_list args;
273        size_t result;
274        va_start( args, fmt );
275        result = fsd_vsnprintf( truncated, str, size, fmt, args );
276        va_end( args );
277        return result;
278}
279
280
281size_t
282fsd_vsnprintf(
283                bool *truncated,
284                char *str, size_t size,
285                const char *fmt, va_list args
286                )
287{
288        int n;
289        char *fmt_buf = NULL;
290        fmt_buf = fsd_expand_printf_ph( fmt );
291        if( fmt_buf )
292                fmt = fmt_buf;
293        n = vsnprintf( str, size, fmt, args );
294        if( fmt_buf )
295                fsd_free( fmt_buf );
296        if( 0 <= n  &&  (size_t)n < size )
297         {}
298        else
299         {
300                str[size-1] = '\0';
301                *truncated = true;
302         }
303        return n;
304}
305
306
307char *
308fsd_asprintf( const char *fmt, ... )
309{
310        va_list args;
311        char *result = NULL;
312        va_start( args, fmt );
313        result = fsd_vasprintf( fmt, args );
314        va_end( args );
315        return result;
316}
317
318
319char *
320fsd_vasprintf( const char *fmt, va_list args )
321{
322        char *result = NULL;
323        char *fmt_buf = NULL;
324        int rc;
325        fmt_buf = fsd_expand_printf_ph( fmt );
326        if( fmt_buf )
327                fmt = fmt_buf;
328        rc = vasprintf( &result, fmt, args );
329        if( fmt_buf )
330                fsd_free( fmt_buf );
331        if( rc == -1 )
332                fsd_exc_raise_sys( ENOMEM );
333        return result;
334}
335
336
337/**
338 * ``%m`` placeholder which is a glibc extension
339 * can be safely used in fsd_*printf functions.
340 */
341char *
342fsd_expand_printf_ph( const char *fmt )
343{
344        char* volatile result = NULL;
345
346        if( strstr(fmt, "%m") == NULL )
347                return result;
348
349        TRY
350         {
351                const char *pos;
352                while( (pos = strstr(fmt, "%m")) != NULL
353                                &&  (pos == fmt  ||  pos[-1] != '%') )
354                 {
355                        char* volatile errno_msg = NULL;
356                        volatile bool own_errno_msg = false;
357                        TRY
358                         {
359                                char *buf = NULL;
360                                size_t fmt_len = strlen(fmt);
361                                size_t ph_pos = pos - fmt;
362                                size_t errno_msg_len;
363                                errno_msg = fsd_astrerror( errno, (bool*)&own_errno_msg );
364                                errno_msg_len = strlen(errno_msg);
365                                fsd_calloc( buf, fmt_len-2+errno_msg_len+1, char );
366                                /* replace ``%m`` with strerror(errno) */
367                                strncat( buf, fmt, ph_pos );
368                                strcat( buf+ph_pos, errno_msg );
369                                strcat( buf+ph_pos+errno_msg_len, fmt+ph_pos+2 );
370                                fsd_free( result );
371                                fmt = result = buf;
372                         }
373                        FINALLY
374                         {
375                                if( errno_msg && own_errno_msg )
376                                        fsd_free( errno_msg );
377                         }
378                        END_TRY
379                 }
380         }
381        EXCEPT_DEFAULT
382         {
383                fsd_free( result );
384                fsd_exc_reraise();
385         }
386        END_TRY
387
388        return result;
389}
390
391
392const char *
393fsd_strerror_r( int errnum, char *buffer, size_t buffer_size )
394{
395#       ifdef HAVE_DECL_STRERROR_R
396#               ifdef _GNU_SOURCE
397                        return strerror_r( errnum, buffer, buffer_size );
398#               else
399                        strerror_r( errnum, buffer, buffer_size );
400                        return buffer;
401#               endif /* !_GNU_SOURCE */
402#       else /* assume strerror is thread safe -- returned string is constant */
403                return strerror(errnum);
404#       endif /* ! HAVE_STRERROR_R */
405}
406
407
408char *
409fsd_astrerror( int errnum, bool *malloced )
410{
411#ifdef HAVE_DECL_STRERROR_R
412        char *buffer = NULL;
413        size_t buffer_size = 0;
414        char *result = NULL;
415
416        do {
417                if( buffer_size == 0 )
418                        buffer_size = 1024;
419                else
420                        buffer_size *= 2;
421                fsd_realloc( buffer, buffer_size, char );
422#               ifdef _GNU_SOURCE
423                result = strerror_r( errnum, buffer, buffer_size );
424                if( result == buffer && strlen(result)+1 == buffer_size )
425                        continue;
426#               else
427                if( strerror_r( errnum, buffer, buffer_size ) && errno == ERANGE )
428                 {
429                        result = buffer;
430                        continue;
431                 }
432#               endif /* !_GNU_SOURCE */
433        } while( false );
434        *malloced = (buffer == result);
435        if( buffer != result )
436                fsd_free( buffer );
437        return result;
438#else /* ! HAVE_DECL_STRERROR_R */
439        /* assume strerror is thread safe -- returned string is constant */
440        *malloced = false;
441        return strerror(errnum);
442#endif /* ! HAVE_DECL_STRERROR_R */
443}
444
445
446void
447fsd_get_time( struct timespec *ts )
448{
449        struct timeval tv;
450        int rc;
451        rc = gettimeofday( &tv, NULL );
452        if( rc )
453                fsd_exc_raise_sys( 0 );
454        else
455         {
456                ts->tv_sec = tv.tv_sec;
457                ts->tv_nsec = 1000 * tv.tv_usec;
458         }
459}
460
461
462void
463fsd_ts_add( struct timespec *a, const struct timespec *b )
464{
465        const int nano = 1000000000;
466        a->tv_sec += b->tv_sec;
467        a->tv_nsec += b->tv_nsec;
468        if( a->tv_nsec >= nano )
469         {
470                a->tv_nsec -= nano;
471                a->tv_sec ++;
472         }
473}
474
475
476int
477fsd_ts_cmp( const struct timespec *a, const struct timespec *b )
478{
479        if( a->tv_sec != b->tv_sec )
480                return a->tv_sec - b->tv_sec;
481        else
482                return a->tv_nsec - b->tv_nsec;
483}
484
485
486void
487fsd_read_file(
488                const char *filename, bool must_exist,
489                char **content, size_t *length
490                )
491{
492        volatile int fd = -1;
493        char* volatile buffer = NULL;
494        size_t size = 0;
495        size_t capacity = 0;
496        ssize_t n_read;
497
498        TRY
499         {
500                *content = NULL;
501                *length = 0;
502
503                fd = open( filename, O_RDONLY );
504                if( fd == -1 )
505                 {
506                        if( errno==ENOENT && !must_exist )
507                         {
508                                *content = NULL;
509                                *length = 0;
510                         }
511                        else
512                                fsd_exc_raise_sys( 0 );
513                 }
514                else
515                 {
516                        do {
517                                capacity = size + 1024;
518                                fsd_realloc( buffer, capacity, char );
519                                n_read = read( fd, buffer, capacity-size );
520                                if( n_read == (ssize_t)-1 )
521                                        fsd_exc_raise_sys( 0 );
522                                else
523                                        size += n_read;
524                        } while( n_read != 0 );
525
526                        fsd_realloc( buffer, size+1, char );
527                        buffer[ size ] = '\0';
528                 }
529         }
530        ELSE
531         {
532                *content = buffer;  buffer = NULL;
533                *length = size;
534         }
535        FINALLY
536         {
537                fsd_free( buffer );
538                if( fd >= 0 )
539                        close( fd );
540         }
541        END_TRY
542}
543
544
545char *
546fsd_getcwd(void)
547{
548        char* volatile buffer = NULL;
549        char* volatile result = NULL;
550        size_t size = 64;
551
552        TRY
553         {
554                fsd_calloc( buffer, size, char );
555                while( true )
556                 {
557                        char *result = getcwd( buffer, size );
558                        if( result != NULL )
559                                break;
560                        else if( errno == ERANGE )
561                         {
562                                size *= 2;
563                                fsd_realloc( buffer, size, char );
564                         }
565                        else
566                                fsd_exc_raise_sys( 0 );
567                 }
568                fsd_realloc( buffer, strlen(buffer)+1, char );
569         }
570        ELSE
571         { result = buffer;  buffer = NULL; }
572        FINALLY
573         { fsd_free( buffer ); }
574        END_TRY
575
576        return result;
577}
578
579
580const char *
581fsd_strsignal( int signum )
582{
583#define DETECT_SIG( signame ) \
584        case signame:  return #signame;
585        switch( signum )
586         {
587                /* signals described by POSIX.1 */
588                DETECT_SIG( SIGHUP  )
589                DETECT_SIG( SIGINT      )
590                DETECT_SIG( SIGQUIT )
591                DETECT_SIG( SIGILL      )
592                DETECT_SIG( SIGABRT )
593                DETECT_SIG( SIGFPE      )
594                DETECT_SIG( SIGKILL )
595                DETECT_SIG( SIGSEGV )
596                DETECT_SIG( SIGPIPE )
597                DETECT_SIG( SIGALRM )
598                DETECT_SIG( SIGTERM )
599                DETECT_SIG( SIGUSR1 )
600                DETECT_SIG( SIGUSR2 )
601                DETECT_SIG( SIGCHLD )
602                DETECT_SIG( SIGCONT )
603                DETECT_SIG( SIGSTOP )
604                DETECT_SIG( SIGTSTP )
605                DETECT_SIG( SIGTTIN )
606                DETECT_SIG( SIGTTOU )
607                /* signals described in SUSv2 and SUSv3 / POSIX 1003.1-2001 */
608#ifdef SIGBUS
609                DETECT_SIG( SIGBUS    )
610#endif
611#ifdef SIGPOLL
612                DETECT_SIG( SIGPOLL       )
613#endif
614#ifdef SIGPROF
615                DETECT_SIG( SIGPROF       )
616#endif
617#ifdef SIGSYS
618                DETECT_SIG( SIGSYS        )
619#endif
620#ifdef SIGTRAP
621                DETECT_SIG( SIGTRAP       )
622#endif
623#ifdef SIGURG
624                DETECT_SIG( SIGURG        )
625#endif
626#ifdef SIGVTALRM
627                DETECT_SIG( SIGVTALRM )
628#endif
629#ifdef SIGXCPU
630                DETECT_SIG( SIGXCPU       )
631#endif
632#ifdef SIGXFSZ
633                DETECT_SIG( SIGXFSZ       )
634#endif
635                default:
636#               ifdef HAVE_SYS_SIGLIST
637                        return sys_siglist[signum];
638#               else
639                        return "unknown signal?!";
640#               endif
641                        break;
642         }
643}
644
Note: See TracBrowser for help on using the repository browser.