darshan-stdio.c 42.8 KB
Newer Older
1 2 3 4 5 6
/*
 * Copyright (C) 2015 University of Chicago.
 * See COPYRIGHT notice in top-level directory.
 *
 */

Philip Carns's avatar
Philip Carns committed
7 8 9 10 11
/* catalog of stdio functions instrumented by this module
 *
 * functions for opening streams
 * --------------
 * FILE    *fdopen(int, const char *);                      DONE
Philip Carns's avatar
Philip Carns committed
12
 * FILE    *fopen(const char *, const char *);              DONE
Philip Carns's avatar
Philip Carns committed
13
 * FILE    *fopen64(const char *, const char *);            DONE
Philip Carns's avatar
Philip Carns committed
14
 * FILE    *freopen(const char *, const char *, FILE *);    DONE
Philip Carns's avatar
Philip Carns committed
15
 * FILE    *freopen64(const char *, const char *, FILE *);  DONE
Philip Carns's avatar
Philip Carns committed
16 17 18 19 20 21 22
 *
 * functions for closing streams
 * --------------
 * int      fclose(FILE *);                                 DONE
 *
 * functions for flushing streams
 * --------------
Philip Carns's avatar
Philip Carns committed
23
 * int      fflush(FILE *);                                 DONE
Philip Carns's avatar
Philip Carns committed
24 25 26
 *
 * functions for reading data
 * --------------
Philip Carns's avatar
Philip Carns committed
27
 * int      fgetc(FILE *);                                  DONE
Philip Carns's avatar
Philip Carns committed
28
 * char    *fgets(char *, int, FILE *);                     DONE
Philip Carns's avatar
Philip Carns committed
29
 * size_t   fread(void *, size_t, size_t, FILE *);          DONE
Philip Carns's avatar
Philip Carns committed
30 31
 * int      fscanf(FILE *, const char *, ...);              DONE
 * int      vfscanf(FILE *, const char *, va_list);         DONE
Philip Carns's avatar
Philip Carns committed
32
 * int      getc(FILE *);                                   DONE
Philip Carns's avatar
Philip Carns committed
33
 * int      getw(FILE *);                                   DONE
Philip Carns's avatar
Philip Carns committed
34 35 36
 *
 * functions for writing data
 * --------------
Philip Carns's avatar
Philip Carns committed
37 38
 * int      fprintf(FILE *, const char *, ...);             DONE
 * int      vfprintf(FILE *, const char *, va_list);        DONE
Philip Carns's avatar
Philip Carns committed
39
 * int      fputc(int, FILE *);                             DONE
Philip Carns's avatar
Philip Carns committed
40
 * int      fputs(const char *, FILE *);                    DONE
Philip Carns's avatar
Philip Carns committed
41
 * size_t   fwrite(const void *, size_t, size_t, FILE *);   DONE
Philip Carns's avatar
Philip Carns committed
42
 * int      putc(int, FILE *);                              DONE
Philip Carns's avatar
Philip Carns committed
43
 * int      putw(int, FILE *);                              DONE
Philip Carns's avatar
Philip Carns committed
44 45 46 47
 *
 * functions for changing file position
 * --------------
 * int      fseek(FILE *, long int, int);                   DONE
Philip Carns's avatar
Philip Carns committed
48
 * int      fseeko(FILE *, off_t, int);                     DONE
Philip Carns's avatar
Philip Carns committed
49
 * int      fseeko64(FILE *, off_t, int);                   DONE
Philip Carns's avatar
Philip Carns committed
50 51
 * int      fsetpos(FILE *, const fpos_t *);                DONE
 * int      fsetpos64(FILE *, const fpos_t *);              DONE
Philip Carns's avatar
Philip Carns committed
52
 * void     rewind(FILE *);                                 DONE
Philip Carns's avatar
Philip Carns committed
53
 *
54 55 56 57 58
 * Omissions: 
 *   - _unlocked() variants of the various flush, read, and write
 *     functions.  There are many of these, but they are not available on all
 *     systems and the man page advises not to use them.
 *   - ungetc()
Philip Carns's avatar
Philip Carns committed
59 60
 */

61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
#define _XOPEN_SOURCE 500
#define _GNU_SOURCE

#include "darshan-runtime-config.h"
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/uio.h>
#include <sys/mman.h>
#include <search.h>
#include <assert.h>
#include <libgen.h>
#include <pthread.h>
Philip Carns's avatar
Philip Carns committed
81 82
#include <stdint.h>
#include <limits.h>
83 84 85 86

#include "darshan.h"
#include "darshan-dynamic.h"

87 88 89 90
#ifndef HAVE_OFF64_T
typedef int64_t off64_t;
#endif

91 92
DARSHAN_FORWARD_DECL(fopen, FILE*, (const char *path, const char *mode));
DARSHAN_FORWARD_DECL(fopen64, FILE*, (const char *path, const char *mode));
Philip Carns's avatar
Philip Carns committed
93
DARSHAN_FORWARD_DECL(fdopen, FILE*, (int fd, const char *mode));
Philip Carns's avatar
Philip Carns committed
94
DARSHAN_FORWARD_DECL(freopen, FILE*, (const char *path, const char *mode, FILE *stream));
Philip Carns's avatar
Philip Carns committed
95
DARSHAN_FORWARD_DECL(freopen64, FILE*, (const char *path, const char *mode, FILE *stream));
96
DARSHAN_FORWARD_DECL(fclose, int, (FILE *fp));
Philip Carns's avatar
Philip Carns committed
97
DARSHAN_FORWARD_DECL(fflush, int, (FILE *fp));
98
DARSHAN_FORWARD_DECL(fwrite, size_t, (const void *ptr, size_t size, size_t nmemb, FILE *stream));
Philip Carns's avatar
Philip Carns committed
99
DARSHAN_FORWARD_DECL(fputc, int, (int c, FILE *stream));
Philip Carns's avatar
Philip Carns committed
100
DARSHAN_FORWARD_DECL(putw, int, (int w, FILE *stream));
Philip Carns's avatar
Philip Carns committed
101
DARSHAN_FORWARD_DECL(fputs, int, (const char *s, FILE *stream));
Philip Carns's avatar
Philip Carns committed
102
DARSHAN_FORWARD_DECL(fprintf, int, (FILE *stream, const char *format, ...));
103
DARSHAN_FORWARD_DECL(printf, int, (const char *format, ...));
Philip Carns's avatar
Philip Carns committed
104
DARSHAN_FORWARD_DECL(vfprintf, int, (FILE *stream, const char *format, va_list));
105
DARSHAN_FORWARD_DECL(vprintf, int, (const char *format, va_list));
106
DARSHAN_FORWARD_DECL(fread, size_t, (void *ptr, size_t size, size_t nmemb, FILE *stream));
Philip Carns's avatar
Philip Carns committed
107
DARSHAN_FORWARD_DECL(fgetc, int, (FILE *stream));
Philip Carns's avatar
Philip Carns committed
108
DARSHAN_FORWARD_DECL(getw, int, (FILE *stream));
Philip Carns's avatar
Philip Carns committed
109
DARSHAN_FORWARD_DECL(_IO_getc, int, (FILE *stream));
Philip Carns's avatar
Philip Carns committed
110
DARSHAN_FORWARD_DECL(_IO_putc, int, (int, FILE *stream));
Philip Carns's avatar
Philip Carns committed
111
DARSHAN_FORWARD_DECL(fscanf, int, (FILE *stream, const char *format, ...));
Philip Carns's avatar
Philip Carns committed
112
DARSHAN_FORWARD_DECL(__isoc99_fscanf, int, (FILE *stream, const char *format, ...));
Philip Carns's avatar
Philip Carns committed
113
DARSHAN_FORWARD_DECL(vfscanf, int, (FILE *stream, const char *format, va_list ap));
Philip Carns's avatar
Philip Carns committed
114
DARSHAN_FORWARD_DECL(fgets, char*, (char *s, int size, FILE *stream));
115
DARSHAN_FORWARD_DECL(fseek, int, (FILE *stream, long offset, int whence));
Philip Carns's avatar
Philip Carns committed
116
DARSHAN_FORWARD_DECL(fseeko, int, (FILE *stream, off_t offset, int whence));
117
DARSHAN_FORWARD_DECL(fseeko64, int, (FILE *stream, off64_t offset, int whence));
Philip Carns's avatar
Philip Carns committed
118
DARSHAN_FORWARD_DECL(fsetpos, int, (FILE *stream, const fpos_t *pos));
119
DARSHAN_FORWARD_DECL(fsetpos64, int, (FILE *stream, const fpos64_t *pos));
Philip Carns's avatar
Philip Carns committed
120
DARSHAN_FORWARD_DECL(rewind, void, (FILE *stream));
121

122 123
/* structure to track stdio stats at runtime */
struct stdio_file_record_ref
124
{
125
    struct darshan_stdio_file* file_rec;
126 127 128 129
    int64_t offset;
    double last_meta_end;
    double last_read_end;
    double last_write_end;
130
    int fs_type;
131 132 133 134 135 136 137 138
};

/* The stdio_runtime structure maintains necessary state for storing
 * STDIO file records and for coordinating with darshan-core at 
 * shutdown time.
 */
struct stdio_runtime
{
139 140 141
    void *rec_id_hash;
    void *stream_hash;
    int file_rec_count;
142 143 144 145 146 147 148
};

static struct stdio_runtime *stdio_runtime = NULL;
static pthread_mutex_t stdio_runtime_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
static int darshan_mem_alignment = 1;
static int my_rank = -1;

149 150 151 152 153 154 155
static void stdio_runtime_initialize(
    void);
static struct stdio_file_record_ref *stdio_track_new_file_record(
    darshan_record_id rec_id, const char *path);
static void stdio_cleanup_runtime(
    void);
#ifdef HAVE_MPI
156 157
static void stdio_record_reduction_op(void* infile_v, void* inoutfile_v,
    int *len, MPI_Datatype *datatype);
158 159 160
static void stdio_shared_record_variance(
    MPI_Comm mod_comm, struct darshan_stdio_file *inrec_array,
    struct darshan_stdio_file *outrec_array, int shared_rec_count);
161 162 163 164 165 166
static void stdio_mpi_redux(
    void *stdio_buf, MPI_Comm mod_comm,
    darshan_record_id *shared_recs, int shared_rec_count);
#endif
static void stdio_shutdown(
    void **stdio_buf, int *stdio_buf_sz);
167

168 169 170
/* extern function def for querying record name from a POSIX fd */
extern char *darshan_posix_lookup_record_name(int fd);

171 172 173 174 175 176
/* we need access to fileno (defined in POSIX module) for instrumenting fopen calls */
#ifdef DARSHAN_PRELOAD
extern int (*__real_fileno)(FILE *stream);
#else
extern int __real_fileno(FILE *stream);
#endif
177

178 179 180
#define STDIO_LOCK() pthread_mutex_lock(&stdio_runtime_mutex)
#define STDIO_UNLOCK() pthread_mutex_unlock(&stdio_runtime_mutex)

181 182
#define STDIO_PRE_RECORD() do { \
    STDIO_LOCK(); \
183
    if(!darshan_core_disabled_instrumentation()) { \
184 185
        if(!stdio_runtime) stdio_runtime_initialize(); \
        if(stdio_runtime) break; \
186
    } \
187 188
    STDIO_UNLOCK(); \
    return(ret); \
189 190 191 192 193 194
} while(0)

#define STDIO_POST_RECORD() do { \
    STDIO_UNLOCK(); \
} while(0)

Philip Carns's avatar
Philip Carns committed
195
#define STDIO_RECORD_OPEN(__ret, __path, __tm1, __tm2) do { \
196 197 198
    darshan_record_id __rec_id; \
    struct stdio_file_record_ref *__rec_ref; \
    char *__newpath; \
199
    int __fd; \
200
    MAP_OR_FAIL(fileno); \
201 202 203 204 205
    if(!__ret || !__path) break; \
    __newpath = darshan_clean_file_path(__path); \
    if(!__newpath) __newpath = (char*)__path; \
    if(darshan_core_excluded_path(__newpath)) { \
        if(__newpath != (char*)__path) free(__newpath); \
206
        break; \
Philip Carns's avatar
Philip Carns committed
207
    } \
208 209 210 211 212
    __rec_id = darshan_core_gen_record_id(__newpath); \
    __rec_ref = darshan_lookup_record_ref(stdio_runtime->rec_id_hash, &__rec_id, sizeof(darshan_record_id)); \
    if(!__rec_ref) __rec_ref = stdio_track_new_file_record(__rec_id, __newpath); \
    if(!__rec_ref) { \
        if(__newpath != (char*)__path) free(__newpath); \
213 214
        break; \
    } \
215
    _STDIO_RECORD_OPEN(__ret, __rec_ref, __tm1, __tm2, 1, -1); \
216
    __fd = __real_fileno(__ret); \
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235
    darshan_instrument_fs_data(__rec_ref->fs_type, __newpath, __fd); \
    if(__newpath != (char*)__path) free(__newpath); \
} while(0)

#define STDIO_RECORD_REFOPEN(__ret, __rec_ref, __tm1, __tm2, __ref_counter) do { \
    if(!ret || !rec_ref) break; \
    _STDIO_RECORD_OPEN(__ret, __rec_ref, __tm1, __tm2, 0, __ref_counter); \
} while(0)

#define _STDIO_RECORD_OPEN(__ret, __rec_ref, __tm1, __tm2, __reset_flag, __ref_counter) do { \
    if(__reset_flag) __rec_ref->offset = 0; \
    __rec_ref->file_rec->counters[STDIO_OPENS] += 1; \
    if(__ref_counter >= 0) __rec_ref->file_rec->counters[__ref_counter] += 1; \
    if(__rec_ref->file_rec->fcounters[STDIO_F_OPEN_START_TIMESTAMP] == 0 || \
     __rec_ref->file_rec->fcounters[STDIO_F_OPEN_START_TIMESTAMP] > __tm1) \
        __rec_ref->file_rec->fcounters[STDIO_F_OPEN_START_TIMESTAMP] = __tm1; \
    __rec_ref->file_rec->fcounters[STDIO_F_OPEN_END_TIMESTAMP] = __tm2; \
    DARSHAN_TIMER_INC_NO_OVERLAP(__rec_ref->file_rec->fcounters[STDIO_F_META_TIME], __tm1, __tm2, __rec_ref->last_meta_end); \
    darshan_add_record_ref(&(stdio_runtime->stream_hash), &(__ret), sizeof(__ret), __rec_ref); \
Philip Carns's avatar
Philip Carns committed
236 237 238
} while(0)


239
#define STDIO_RECORD_READ(__fp, __bytes,  __tm1, __tm2) do{ \
240
    struct stdio_file_record_ref* rec_ref; \
241
    int64_t this_offset; \
Philip Carns's avatar
Philip Carns committed
242
    rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &(__fp), sizeof(__fp)); \
243 244 245 246 247 248 249 250 251 252 253
    if(!rec_ref) break; \
    this_offset = rec_ref->offset; \
    rec_ref->offset = this_offset + __bytes; \
    if(rec_ref->file_rec->counters[STDIO_MAX_BYTE_READ] < (this_offset + __bytes - 1)) \
        rec_ref->file_rec->counters[STDIO_MAX_BYTE_READ] = (this_offset + __bytes - 1); \
    rec_ref->file_rec->counters[STDIO_BYTES_READ] += __bytes; \
    rec_ref->file_rec->counters[STDIO_READS] += 1; \
    if(rec_ref->file_rec->fcounters[STDIO_F_READ_START_TIMESTAMP] == 0 || \
     rec_ref->file_rec->fcounters[STDIO_F_READ_START_TIMESTAMP] > __tm1) \
        rec_ref->file_rec->fcounters[STDIO_F_READ_START_TIMESTAMP] = __tm1; \
    rec_ref->file_rec->fcounters[STDIO_F_READ_END_TIMESTAMP] = __tm2; \
254
    DARSHAN_TIMER_INC_NO_OVERLAP(rec_ref->file_rec->fcounters[STDIO_F_READ_TIME], __tm1, __tm2, rec_ref->last_read_end); \
255 256
} while(0)

Philip Carns's avatar
Philip Carns committed
257
#define STDIO_RECORD_WRITE(__fp, __bytes,  __tm1, __tm2, __fflush_flag) do{ \
258
    struct stdio_file_record_ref* rec_ref; \
259
    int64_t this_offset; \
Philip Carns's avatar
Philip Carns committed
260
    rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &(__fp), sizeof(__fp)); \
261 262 263 264 265 266
    if(!rec_ref) break; \
    this_offset = rec_ref->offset; \
    rec_ref->offset = this_offset + __bytes; \
    if(rec_ref->file_rec->counters[STDIO_MAX_BYTE_WRITTEN] < (this_offset + __bytes - 1)) \
        rec_ref->file_rec->counters[STDIO_MAX_BYTE_WRITTEN] = (this_offset + __bytes - 1); \
    rec_ref->file_rec->counters[STDIO_BYTES_WRITTEN] += __bytes; \
Philip Carns's avatar
Philip Carns committed
267
    if(__fflush_flag) \
268
        rec_ref->file_rec->counters[STDIO_FLUSHES] += 1; \
Philip Carns's avatar
Philip Carns committed
269
    else \
270 271 272 273 274 275
        rec_ref->file_rec->counters[STDIO_WRITES] += 1; \
    if(rec_ref->file_rec->fcounters[STDIO_F_WRITE_START_TIMESTAMP] == 0 || \
     rec_ref->file_rec->fcounters[STDIO_F_WRITE_START_TIMESTAMP] > __tm1) \
        rec_ref->file_rec->fcounters[STDIO_F_WRITE_START_TIMESTAMP] = __tm1; \
    rec_ref->file_rec->fcounters[STDIO_F_WRITE_END_TIMESTAMP] = __tm2; \
    DARSHAN_TIMER_INC_NO_OVERLAP(rec_ref->file_rec->fcounters[STDIO_F_WRITE_TIME], __tm1, __tm2, rec_ref->last_write_end); \
276
} while(0)
Philip Carns's avatar
Philip Carns committed
277

Philip Carns's avatar
Philip Carns committed
278
FILE* DARSHAN_DECL(fopen)(const char *path, const char *mode)
Philip Carns's avatar
Philip Carns committed
279 280 281 282
{
    FILE* ret;
    double tm1, tm2;

Philip Carns's avatar
Philip Carns committed
283
    MAP_OR_FAIL(fopen);
Philip Carns's avatar
Philip Carns committed
284 285

    tm1 = darshan_core_wtime();
Philip Carns's avatar
Philip Carns committed
286
    ret = __real_fopen(path, mode);
Philip Carns's avatar
Philip Carns committed
287 288
    tm2 = darshan_core_wtime();

289
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
290
    STDIO_RECORD_OPEN(ret, path, tm1, tm2);
291
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
292 293 294 295

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
296
FILE* DARSHAN_DECL(fopen64)(const char *path, const char *mode)
297 298
{
    FILE* ret;
Philip Carns's avatar
Philip Carns committed
299
    double tm1, tm2;
300

Shane Snyder's avatar
Shane Snyder committed
301
    MAP_OR_FAIL(fopen64);
302

Philip Carns's avatar
Philip Carns committed
303
    tm1 = darshan_core_wtime();
Philip Carns's avatar
Philip Carns committed
304
    ret = __real_fopen64(path, mode);
Philip Carns's avatar
Philip Carns committed
305 306
    tm2 = darshan_core_wtime();

307
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
308
    STDIO_RECORD_OPEN(ret, path, tm1, tm2);
309
    STDIO_POST_RECORD();
310 311 312 313

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
314
FILE* DARSHAN_DECL(fdopen)(int fd, const char *mode)
315 316
{
    FILE* ret;
Philip Carns's avatar
Philip Carns committed
317
    double tm1, tm2;
318 319
    darshan_record_id rec_id;
    struct stdio_file_record_ref *rec_ref;
320

Philip Carns's avatar
Philip Carns committed
321
    MAP_OR_FAIL(fdopen);
322

Philip Carns's avatar
Philip Carns committed
323
    tm1 = darshan_core_wtime();
Philip Carns's avatar
Philip Carns committed
324 325 326
    ret = __real_fdopen(fd, mode);
    tm2 = darshan_core_wtime();

327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343
    if(ret)
    {
        char *rec_name = darshan_posix_lookup_record_name(fd);
        if(rec_name)
        {
            rec_id = darshan_core_gen_record_id(rec_name);

            STDIO_PRE_RECORD();
            rec_ref = darshan_lookup_record_ref(stdio_runtime->rec_id_hash,
                &rec_id, sizeof(darshan_record_id));
            if(!rec_ref)
                rec_ref = stdio_track_new_file_record(rec_id, rec_name);
            STDIO_RECORD_REFOPEN(ret, rec_ref, tm1, tm2, STDIO_FDOPENS);
            STDIO_POST_RECORD();
        }
    }

Philip Carns's avatar
Philip Carns committed
344 345 346 347 348 349 350 351 352 353 354 355 356

    return(ret);
}

FILE* DARSHAN_DECL(freopen)(const char *path, const char *mode, FILE *stream)
{
    FILE* ret;
    double tm1, tm2;

    MAP_OR_FAIL(freopen);

    tm1 = darshan_core_wtime();
    ret = __real_freopen(path, mode, stream);
Philip Carns's avatar
Philip Carns committed
357 358
    tm2 = darshan_core_wtime();

359
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
360
    STDIO_RECORD_OPEN(ret, path, tm1, tm2);
361
    STDIO_POST_RECORD();
362 363 364 365

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
366 367 368 369 370 371 372 373 374 375 376
FILE* DARSHAN_DECL(freopen64)(const char *path, const char *mode, FILE *stream)
{
    FILE* ret;
    double tm1, tm2;

    MAP_OR_FAIL(freopen64);

    tm1 = darshan_core_wtime();
    ret = __real_freopen64(path, mode, stream);
    tm2 = darshan_core_wtime();

377
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
378
    STDIO_RECORD_OPEN(ret, path, tm1, tm2);
379
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
380 381 382 383 384

    return(ret);
}


Philip Carns's avatar
Philip Carns committed
385 386 387 388 389 390 391 392 393 394 395
int DARSHAN_DECL(fflush)(FILE *fp)
{
    double tm1, tm2;
    int ret;

    MAP_OR_FAIL(fflush);

    tm1 = darshan_core_wtime();
    ret = __real_fflush(fp);
    tm2 = darshan_core_wtime();

396
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
397 398
    if(ret >= 0)
        STDIO_RECORD_WRITE(fp, 0, tm1, tm2, 1);
399
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
400 401 402 403

    return(ret);
}

404 405 406 407
int DARSHAN_DECL(fclose)(FILE *fp)
{
    double tm1, tm2;
    int ret;
408
    struct stdio_file_record_ref *rec_ref;
409 410 411 412 413 414 415

    MAP_OR_FAIL(fclose);

    tm1 = darshan_core_wtime();
    ret = __real_fclose(fp);
    tm2 = darshan_core_wtime();

416 417 418
    STDIO_PRE_RECORD();
    rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &fp, sizeof(fp));
    if(rec_ref)
419
    {
420 421 422 423
        if(rec_ref->file_rec->fcounters[STDIO_F_CLOSE_START_TIMESTAMP] == 0 ||
         rec_ref->file_rec->fcounters[STDIO_F_CLOSE_START_TIMESTAMP] > tm1)
           rec_ref->file_rec->fcounters[STDIO_F_CLOSE_START_TIMESTAMP] = tm1;
        rec_ref->file_rec->fcounters[STDIO_F_CLOSE_END_TIMESTAMP] = tm2;
424
        DARSHAN_TIMER_INC_NO_OVERLAP(
425 426 427
            rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
            tm1, tm2, rec_ref->last_meta_end);
        darshan_delete_record_ref(&(stdio_runtime->stream_hash), &fp, sizeof(fp));
428
    }
429
    STDIO_POST_RECORD();
430 431 432 433

    return(ret);
}

434 435 436 437 438 439 440 441 442 443 444
size_t DARSHAN_DECL(fwrite)(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
    size_t ret;
    double tm1, tm2;

    MAP_OR_FAIL(fwrite);

    tm1 = darshan_core_wtime();
    ret = __real_fwrite(ptr, size, nmemb, stream);
    tm2 = darshan_core_wtime();

445
    STDIO_PRE_RECORD();
446
    if(ret > 0)
Philip Carns's avatar
Philip Carns committed
447
        STDIO_RECORD_WRITE(stream, size*ret, tm1, tm2, 0);
448
    STDIO_POST_RECORD();
449 450 451 452

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
453 454 455 456 457 458 459 460 461 462 463 464

int DARSHAN_DECL(fputc)(int c, FILE *stream)
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(fputc);

    tm1 = darshan_core_wtime();
    ret = __real_fputc(c, stream);
    tm2 = darshan_core_wtime();

465
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
466 467
    if(ret != EOF)
        STDIO_RECORD_WRITE(stream, 1, tm1, tm2, 0);
468
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
469 470 471 472

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
473 474 475 476 477 478 479 480 481 482 483
int DARSHAN_DECL(putw)(int w, FILE *stream)
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(putw);

    tm1 = darshan_core_wtime();
    ret = __real_putw(w, stream);
    tm2 = darshan_core_wtime();

484
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
485 486
    if(ret != EOF)
        STDIO_RECORD_WRITE(stream, sizeof(int), tm1, tm2, 0);
487
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
488 489 490 491 492

    return(ret);
}


Philip Carns's avatar
Philip Carns committed
493 494 495 496 497 498 499 500 501 502 503 504

int DARSHAN_DECL(fputs)(const char *s, FILE *stream)
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(fputs);

    tm1 = darshan_core_wtime();
    ret = __real_fputs(s, stream);
    tm2 = darshan_core_wtime();

505
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
506 507
    if(ret != EOF && ret > 0)
        STDIO_RECORD_WRITE(stream, strlen(s), tm1, tm2, 0);
508
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
509 510 511 512

    return(ret);
}

513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
int DARSHAN_DECL(vprintf)(const char *format, va_list ap)
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(vprintf);

    tm1 = darshan_core_wtime();
    ret = __real_vprintf(format, ap);
    tm2 = darshan_core_wtime();

    STDIO_PRE_RECORD();
    if(ret > 0)
        STDIO_RECORD_WRITE(stdout, ret, tm1, tm2, 0);
    STDIO_POST_RECORD();

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
532 533 534 535 536 537 538 539 540 541 542
int DARSHAN_DECL(vfprintf)(FILE *stream, const char *format, va_list ap)
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(vfprintf);

    tm1 = darshan_core_wtime();
    ret = __real_vfprintf(stream, format, ap);
    tm2 = darshan_core_wtime();

543
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
544
    if(ret > 0)
545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
        STDIO_RECORD_WRITE(stream, ret, tm1, tm2, 0);
    STDIO_POST_RECORD();

    return(ret);
}


int DARSHAN_DECL(printf)(const char *format, ...)
{
    int ret;
    double tm1, tm2;
    va_list ap;

    MAP_OR_FAIL(vprintf);

    tm1 = darshan_core_wtime();
    /* NOTE: we intentionally switch to vprintf here to handle the variable
     * length arguments.
     */
    va_start(ap, format);
    ret = __real_vprintf(format, ap);
    va_end(ap);
    tm2 = darshan_core_wtime();

    STDIO_PRE_RECORD();
    if(ret > 0)
        STDIO_RECORD_WRITE(stdout, ret, tm1, tm2, 0);
572
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593

    return(ret);
}

int DARSHAN_DECL(fprintf)(FILE *stream, const char *format, ...)
{
    int ret;
    double tm1, tm2;
    va_list ap;

    MAP_OR_FAIL(vfprintf);

    tm1 = darshan_core_wtime();
    /* NOTE: we intentionally switch to vfprintf here to handle the variable
     * length arguments.
     */
    va_start(ap, format);
    ret = __real_vfprintf(stream, format, ap);
    va_end(ap);
    tm2 = darshan_core_wtime();

594
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
595
    if(ret > 0)
596
        STDIO_RECORD_WRITE(stream, ret, tm1, tm2, 0);
597
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
598 599 600 601

    return(ret);
}

602 603 604 605 606 607 608 609 610 611 612
size_t DARSHAN_DECL(fread)(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
    size_t ret;
    double tm1, tm2;

    MAP_OR_FAIL(fread);

    tm1 = darshan_core_wtime();
    ret = __real_fread(ptr, size, nmemb, stream);
    tm2 = darshan_core_wtime();

613
    STDIO_PRE_RECORD();
614 615
    if(ret > 0)
        STDIO_RECORD_READ(stream, size*ret, tm1, tm2);
616
    STDIO_POST_RECORD();
617 618 619 620

    return(ret);
}

621
int DARSHAN_DECL(fgetc)(FILE *stream)
Philip Carns's avatar
Philip Carns committed
622 623 624 625 626 627 628 629 630 631
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(fgetc);

    tm1 = darshan_core_wtime();
    ret = __real_fgetc(stream);
    tm2 = darshan_core_wtime();

632
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
633 634
    if(ret != EOF)
        STDIO_RECORD_READ(stream, 1, tm1, tm2);
635
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
636 637 638 639 640

    return(ret);
}

/* NOTE: stdio.h typically implements getc() as a macro pointing to _IO_getc */
641
int DARSHAN_DECL(_IO_getc)(FILE *stream)
Philip Carns's avatar
Philip Carns committed
642 643 644 645 646 647 648 649 650 651
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(_IO_getc);

    tm1 = darshan_core_wtime();
    ret = __real__IO_getc(stream);
    tm2 = darshan_core_wtime();

652
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
653 654
    if(ret != EOF)
        STDIO_RECORD_READ(stream, 1, tm1, tm2);
655
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
656 657 658 659

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
660
/* NOTE: stdio.h typically implements putc() as a macro pointing to _IO_putc */
661
int DARSHAN_DECL(_IO_putc)(int c, FILE *stream)
Philip Carns's avatar
Philip Carns committed
662 663 664 665 666 667 668 669 670 671
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(_IO_putc);

    tm1 = darshan_core_wtime();
    ret = __real__IO_putc(c, stream);
    tm2 = darshan_core_wtime();

672
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
673 674
    if(ret != EOF)
        STDIO_RECORD_WRITE(stream, 1, tm1, tm2, 0);
675
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
676 677 678

    return(ret);
}
679 680

int DARSHAN_DECL(getw)(FILE *stream)
Philip Carns's avatar
Philip Carns committed
681 682 683 684 685 686 687 688 689 690
{
    int ret;
    double tm1, tm2;

    MAP_OR_FAIL(getw);

    tm1 = darshan_core_wtime();
    ret = __real_getw(stream);
    tm2 = darshan_core_wtime();

691
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
692 693
    if(ret != EOF || ferror(stream) == 0)
        STDIO_RECORD_READ(stream, sizeof(int), tm1, tm2);
694
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
695 696 697 698

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721
/* NOTE: some glibc versions use __isoc99_fscanf as the underlying symbol
 * rather than fscanf
 */
int DARSHAN_DECL(__isoc99_fscanf)(FILE *stream, const char *format, ...)
{
    int ret;
    double tm1, tm2;
    va_list ap;
    long start_off, end_off;

    MAP_OR_FAIL(vfscanf);

    tm1 = darshan_core_wtime();
    /* NOTE: we intentionally switch to vfscanf here to handle the variable
     * length arguments.
     */
    start_off = ftell(stream);
    va_start(ap, format);
    ret = __real_vfscanf(stream, format, ap);
    va_end(ap);
    end_off = ftell(stream);
    tm2 = darshan_core_wtime();

722
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
723 724
    if(ret != 0)
        STDIO_RECORD_READ(stream, (end_off-start_off), tm1, tm2);
725
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
726 727 728 729

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
730

Philip Carns's avatar
Philip Carns committed
731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750
int DARSHAN_DECL(fscanf)(FILE *stream, const char *format, ...)
{
    int ret;
    double tm1, tm2;
    va_list ap;
    long start_off, end_off;

    MAP_OR_FAIL(vfscanf);

    tm1 = darshan_core_wtime();
    /* NOTE: we intentionally switch to vfscanf here to handle the variable
     * length arguments.
     */
    start_off = ftell(stream);
    va_start(ap, format);
    ret = __real_vfscanf(stream, format, ap);
    va_end(ap);
    end_off = ftell(stream);
    tm2 = darshan_core_wtime();

751
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
752
    if(ret != 0)
Philip Carns's avatar
Philip Carns committed
753
        STDIO_RECORD_READ(stream, (end_off-start_off), tm1, tm2);
754
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772

    return(ret);
}

int DARSHAN_DECL(vfscanf)(FILE *stream, const char *format, va_list ap)
{
    int ret;
    double tm1, tm2;
    long start_off, end_off;

    MAP_OR_FAIL(vfscanf);

    tm1 = darshan_core_wtime();
    start_off = ftell(stream);
    ret = __real_vfscanf(stream, format, ap);
    end_off = ftell(stream);
    tm2 = darshan_core_wtime();

773
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
774 775
    if(ret != 0)
        STDIO_RECORD_READ(stream, end_off-start_off, tm1, tm2);
776
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
777 778 779 780 781

    return(ret);
}


Philip Carns's avatar
Philip Carns committed
782 783 784 785 786 787 788 789 790 791 792
char* DARSHAN_DECL(fgets)(char *s, int size, FILE *stream)
{
    char *ret;
    double tm1, tm2;

    MAP_OR_FAIL(fgets);

    tm1 = darshan_core_wtime();
    ret = __real_fgets(s, size, stream);
    tm2 = darshan_core_wtime();

793
    STDIO_PRE_RECORD();
Philip Carns's avatar
Philip Carns committed
794 795
    if(ret != NULL)
        STDIO_RECORD_READ(stream, strlen(ret), tm1, tm2);
796
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
797 798 799 800 801

    return(ret);
}


Philip Carns's avatar
Philip Carns committed
802 803 804
void DARSHAN_DECL(rewind)(FILE *stream)
{
    double tm1, tm2;
805
    struct stdio_file_record_ref *rec_ref;
Philip Carns's avatar
Philip Carns committed
806 807 808 809 810 811 812

    MAP_OR_FAIL(rewind);

    tm1 = darshan_core_wtime();
    __real_rewind(stream);
    tm2 = darshan_core_wtime();

813 814 815
    /* NOTE: we don't use STDIO_PRE_RECORD here because there is no return
     * value in this wrapper.
     */
Philip Carns's avatar
Philip Carns committed
816
    STDIO_LOCK();
817
    if(darshan_core_disabled_instrumentation()) {
818 819 820 821
        STDIO_UNLOCK();
        return;
    }
    if(!stdio_runtime) stdio_runtime_initialize();
822 823 824 825 826 827 828 829
    if(!stdio_runtime) {
        STDIO_UNLOCK();
        return;
    }

    rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));

    if(rec_ref)
Philip Carns's avatar
Philip Carns committed
830
    {
831
        rec_ref->offset = 0;
Philip Carns's avatar
Philip Carns committed
832
        DARSHAN_TIMER_INC_NO_OVERLAP(
833 834 835
            rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
            tm1, tm2, rec_ref->last_meta_end);
        rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
Philip Carns's avatar
Philip Carns committed
836
    }
837
    STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
838 839 840 841

    return;
}

842 843 844
int DARSHAN_DECL(fseek)(FILE *stream, long offset, int whence)
{
    int ret;
845
    struct stdio_file_record_ref *rec_ref;
846 847 848 849 850 851 852 853 854 855
    double tm1, tm2;

    MAP_OR_FAIL(fseek);

    tm1 = darshan_core_wtime();
    ret = __real_fseek(stream, offset, whence);
    tm2 = darshan_core_wtime();

    if(ret >= 0)
    {
856 857 858
        STDIO_PRE_RECORD();
        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
        if(rec_ref)
Philip Carns's avatar
Philip Carns committed
859
        {
860
            rec_ref->offset = ftell(stream);
Philip Carns's avatar
Philip Carns committed
861
            DARSHAN_TIMER_INC_NO_OVERLAP(
862 863 864
                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
                tm1, tm2, rec_ref->last_meta_end);
            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
Philip Carns's avatar
Philip Carns committed
865
        }
866
        STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
867 868 869 870 871 872 873 874
    }

    return(ret);
}

int DARSHAN_DECL(fseeko)(FILE *stream, off_t offset, int whence)
{
    int ret;
875
    struct stdio_file_record_ref *rec_ref;
Philip Carns's avatar
Philip Carns committed
876 877 878 879 880 881 882 883 884 885
    double tm1, tm2;

    MAP_OR_FAIL(fseeko);

    tm1 = darshan_core_wtime();
    ret = __real_fseeko(stream, offset, whence);
    tm2 = darshan_core_wtime();

    if(ret >= 0)
    {
886 887 888
        STDIO_PRE_RECORD();
        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
        if(rec_ref)
Philip Carns's avatar
Philip Carns committed
889
        {
890
            rec_ref->offset = ftell(stream);
Philip Carns's avatar
Philip Carns committed
891
            DARSHAN_TIMER_INC_NO_OVERLAP(
892 893 894
                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
                tm1, tm2, rec_ref->last_meta_end);
            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
Philip Carns's avatar
Philip Carns committed
895
        }
896
        STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
897 898 899 900 901
    }

    return(ret);
}

902
int DARSHAN_DECL(fseeko64)(FILE *stream, off64_t offset, int whence)
Philip Carns's avatar
Philip Carns committed
903 904
{
    int ret;
905
    struct stdio_file_record_ref *rec_ref;
Philip Carns's avatar
Philip Carns committed
906 907 908 909 910 911 912 913 914 915
    double tm1, tm2;

    MAP_OR_FAIL(fseeko64);

    tm1 = darshan_core_wtime();
    ret = __real_fseeko64(stream, offset, whence);
    tm2 = darshan_core_wtime();

    if(ret >= 0)
    {
916 917 918
        STDIO_PRE_RECORD();
        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
        if(rec_ref)
919
        {
920
            rec_ref->offset = ftell(stream);
921
            DARSHAN_TIMER_INC_NO_OVERLAP(
922 923 924
                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
                tm1, tm2, rec_ref->last_meta_end);
            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
925
        }
926
        STDIO_POST_RECORD();
927 928 929 930 931
    }

    return(ret);
}

Philip Carns's avatar
Philip Carns committed
932 933 934
int DARSHAN_DECL(fsetpos)(FILE *stream, const fpos_t *pos)
{
    int ret;
935
    struct stdio_file_record_ref *rec_ref;
Philip Carns's avatar
Philip Carns committed
936 937 938 939 940 941 942 943 944 945
    double tm1, tm2;

    MAP_OR_FAIL(fsetpos);

    tm1 = darshan_core_wtime();
    ret = __real_fsetpos(stream, pos);
    tm2 = darshan_core_wtime();

    if(ret >= 0)
    {
946 947 948
        STDIO_PRE_RECORD();
        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
        if(rec_ref)
Philip Carns's avatar
Philip Carns committed
949
        {
950
            rec_ref->offset = ftell(stream);
Philip Carns's avatar
Philip Carns committed
951
            DARSHAN_TIMER_INC_NO_OVERLAP(
952 953 954
                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
                tm1, tm2, rec_ref->last_meta_end);
            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
Philip Carns's avatar
Philip Carns committed
955
        }
956
        STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
957 958 959 960 961
    }

    return(ret);
}

962
int DARSHAN_DECL(fsetpos64)(FILE *stream, const fpos64_t *pos)
Philip Carns's avatar
Philip Carns committed
963 964
{
    int ret;
965
    struct stdio_file_record_ref *rec_ref;
Philip Carns's avatar
Philip Carns committed
966 967 968 969 970 971 972 973 974 975
    double tm1, tm2;

    MAP_OR_FAIL(fsetpos64);

    tm1 = darshan_core_wtime();
    ret = __real_fsetpos64(stream, pos);
    tm2 = darshan_core_wtime();

    if(ret >= 0)
    {
976 977 978
        STDIO_PRE_RECORD();
        rec_ref = darshan_lookup_record_ref(stdio_runtime->stream_hash, &stream, sizeof(stream));
        if(rec_ref)
Philip Carns's avatar
Philip Carns committed
979
        {
980
            rec_ref->offset = ftell(stream);
Philip Carns's avatar
Philip Carns committed
981
            DARSHAN_TIMER_INC_NO_OVERLAP(
982 983 984
                rec_ref->file_rec->fcounters[STDIO_F_META_TIME],
                tm1, tm2, rec_ref->last_meta_end);
            rec_ref->file_rec->counters[STDIO_SEEKS] += 1;
Philip Carns's avatar
Philip Carns committed
985
        }
986
        STDIO_POST_RECORD();
Philip Carns's avatar
Philip Carns committed
987 988 989 990 991
    }

    return(ret);
}

992 993 994 995 996 997 998
/**********************************************************
 * Internal functions for manipulating STDIO module state *
 **********************************************************/

/* initialize internal STDIO module data structures and register with darshan-core */
static void stdio_runtime_initialize()
{
999
    int stdio_buf_size;
1000 1001 1002 1003 1004 1005
    darshan_module_funcs mod_funcs = {
#ifdef HAVE_MPI
    .mod_redux_func = &stdio_mpi_redux,
#endif
    .mod_shutdown_func = &stdio_shutdown
    };
1006 1007 1008

    /* try to store default number of records for this module */
    stdio_buf_size = DARSHAN_DEF_MOD_REC_COUNT * sizeof(struct darshan_stdio_file);
1009 1010 1011 1012

    /* register the stdio module with darshan core */
    darshan_core_register_module(
        DARSHAN_STDIO_MOD,
1013
        mod_funcs,
1014
        &stdio_buf_size,
1015
        &my_rank,
1016 1017
        &darshan_mem_alignment);

1018 1019 1020
    /* return if darshan-core does not provide enough module memory */
    if(stdio_buf_size < sizeof(struct darshan_stdio_file))
    {
Shane Snyder's avatar
Shane Snyder committed
1021
        darshan_core_unregister_module(DARSHAN_STDIO_MOD);
1022
        return;
1023
    }
1024 1025 1026 1027

    stdio_runtime = malloc(sizeof(*stdio_runtime));
    if(!stdio_runtime)
    {
1028
        darshan_core_unregister_module(DARSHAN_STDIO_MOD);
1029 1030
        return;
    }
1031
    memset(stdio_runtime, 0, sizeof(*stdio_runtime));
1032 1033 1034 1035 1036

    /* instantiate records for stdin, stdout, and stderr */
    STDIO_RECORD_OPEN(stdin, "<STDIN>", 0, 0);
    STDIO_RECORD_OPEN(stdout, "<STDOUT>", 0, 0);
    STDIO_RECORD_OPEN(stderr, "<STDERR>", 0, 0);
1037 1038
}

1039 1040 1041 1042 1043 1044 1045
static struct stdio_file_record_ref *stdio_track_new_file_record(
    darshan_record_id rec_id, const char *path)
{
    struct darshan_stdio_file *file_rec = NULL;
    struct stdio_file_record_ref *rec_ref = NULL;
    struct darshan_fs_info fs_info;
    int ret;
1046

1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084