/*___INFO__MARK_BEGIN__*/ /************************************************************************* * * The Contents of this file are made available subject to the terms of * the Sun Industry Standards Source License Version 1.2 * * Sun Microsystems Inc., March, 2001 * * * Sun Industry Standards Source License Version 1.2 * ================================================= * The contents of this file are subject to the Sun Industry Standards * Source License Version 1.2 (the "License"); You may not use this file * except in compliance with the License. You may obtain a copy of the * License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html * * Software provided under this License is provided on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. * See the License for the specific provisions governing your rights and * obligations concerning the Software. * * The Initial Developer of the Original Code is: Sun Microsystems, Inc. * * Copyright: 2001 by Sun Microsystems, Inc. * * All Rights Reserved. * ************************************************************************/ /*___INFO__MARK_END__*/ #include #include #include #include #include #include #include #include "uti/sge_io.h" #include "uti/sge_stdio.h" #include "uti/sge_stdlib.h" #include "uti/sge_unistd.h" #include "sgermon.h" #include "sge_log.h" #include "msg_utilib.h" #define BUFFER 4096 #define FILE_CHUNK (100*1024) /****** uti/io/sge_readnbytes() *********************************************** * NAME * sge_readnbytes() -- Read n bytes from file descriptor * * SYNOPSIS * int sge_readnbytes(int sfd, char *ptr, * int n) * * FUNCTION * Read n bytes from file descriptor. * * INPUTS * int sfd - file descriptor * char *ptr - pointer to buffer * int n - number of bytes * * RESULT * int - number of bytes read * * SEE ALSO * uti/io/sge_writenbytes() * * NOTES * MT-NOTE: sge_readnbytes() is MT safe ******************************************************************************/ int sge_readnbytes(int sfd, char *ptr, int n) { int i; /* number of bytes read */ int nleft = n; /* number of bytes still to read */ DENTER(BASIS_LAYER, "sge_readnbytes"); DPRINTF(("TOTAL BYTES TO BE READ %d\n", n)); /* Read n bytes */ while (nleft > 0) { i = read(sfd, ptr, nleft); DPRINTF(("read %d bytes on fd %d\n", i, sfd)); if (i < 0) { DPRINTF(("sge_readnbytes: returning %d\n", i)); DEXIT; return (i); } else { if (i == 0) break; } nleft -= i; ptr += i; } DPRINTF(("sge_readnbytes: returning %d\n", nleft)); DEXIT; return (n - nleft); } /****** uti/io/sge_writenbytes() ********************************************** * NAME * sge_writenbytes() -- Write n bytes to file descriptor * * SYNOPSIS * int sge_writenbytes(int sfd, const char *ptr, * int n) * * FUNCTION * Write n bytes to file descriptor * * INPUTS * int sfd - file descriptor * const char *ptr - pointer to buffer * int n - number of bytes * * RESULT * int - number of bytes written * * SEE ALSO * uti/io/sge_readnbytes() * * NOTES * MT-NOTE: sge_writenbytes() is MT safe ******************************************************************************/ int sge_writenbytes(int sfd, const char *ptr, int n) { int i; /* number of bytes written */ int nleft = n; /* number of bytes still to write */ DENTER(BASIS_LAYER, "sge_writenbytes"); /* Write n bytes */ while (nleft > 0) { DTRACE; i = write(sfd, ptr, nleft); if (i == -1) { DPRINTF(("write failed with error %d: %s\n", i, strerror(errno))); } else { DPRINTF(("wrote %d bytes on fd %d\n", i, sfd)); } if (i <= 0) { DPRINTF(("sge_writenbytes: returning %d\n", i)); DEXIT; return (i); } nleft -= i; ptr += i; } DEXIT; return (n); } /****** uti/io/sge_filecmp() ************************************************** * NAME * sge_filecmp() -- Compare two files * * SYNOPSIS * int sge_filecmp(const char *name0, const char *name1) * * FUNCTION * Compare two files. They are equal if: * - both of them have the same name * - if a stat() succeeds for both files and * i-node/device-id are equal * * we are not sure * - if stat() failes for at least one of the files * (It could be that both pathes direct to the same * file not existing) * * INPUTS * const char *name0 - 1st filename * const char *name1 - 2nd filename * * RESULT * int - Identical? * 0 - Yes. * 1 - No they are not equivalent. * * NOTES * MT-NOTE: sge_filecmp() is MT safe ******************************************************************************/ int sge_filecmp(const char *name0, const char *name1) { SGE_STRUCT_STAT buf0, buf1; DENTER(TOP_LAYER, "filecmp"); if (!strcmp(name0, name1)) { DEXIT; return 0; } if (SGE_STAT(name0, &buf0)<0) { DEXIT; return 1; } if (SGE_STAT(name1, &buf1)<0) { DEXIT; return 1; } if (buf0.st_ino == buf1.st_ino && buf0.st_dev == buf1.st_dev) { DEXIT; return 0; } else { DEXIT; return 1; } } /****** uti/io/sge_copy_append() ********************************************** * NAME * sge_copy_append() -- Copy/append one file to another * * SYNOPSIS * int sge_copy_append(char *src, const char *dst, * sge_mode_t mode) * * FUNCTION * Copy/append content from 'src' to 'dst' * * INPUTS * char *src - source filename * const char *dst - destination filename * sge_mode_t mode - mode * * RESULT * int - error state * 0 - OK * -1 - Error * * SEE ALSO * uti/io/sge_mode_t * * NOTES * MT-NOTE: sge_copy_append() is MT safe ******************************************************************************/ int sge_copy_append(char *src, const char *dst, sge_mode_t mode) { #define CPBUF 1024 char buf[CPBUF]; int fdsrc, fddst, modus, rs, ws; bool error; DENTER(TOP_LAYER, "sge_copy_append"); if (src == NULL || dst == NULL || strlen(src) == 0 || strlen(dst) == 0 || !(mode == SGE_MODE_APPEND || mode == SGE_MODE_COPY)) { DEXIT; return -1; } if (!strcmp(src, dst)) { DEXIT; return -1; } /* Return if source file doesn't exist */ if ((fdsrc = SGE_OPEN2(src, O_RDONLY)) == -1) { DEXIT; return -1; } if (mode == SGE_MODE_APPEND) modus = O_WRONLY | O_APPEND | O_CREAT; else modus = O_WRONLY | O_CREAT; if ((fddst = SGE_OPEN3(dst, modus, 0666)) == -1) { DEXIT; return -1; } error = false; while (!error) { rs = read(fdsrc, buf, 512); if (rs == -1 && errno == EINTR) continue; else if (rs == -1) error = true; if (!error && rs > 0) { while (!error) { ws = write(fddst, buf, rs); if (ws == -1 && errno == EINTR) continue; else if (ws == -1) { error = true; break; } else break; } } if (error) break; if (rs == 0) break; } close(fdsrc); close(fddst); DEXIT; return (error ? -1: 0); } /****** uti/io/sge_bin2string() *********************************************** * NAME * sge_bin2string() -- Put binary stream into a string * * SYNOPSIS * char* sge_bin2string(FILE *fp, int size) * * FUNCTION * Read a binary steam from given file descriptor 'fp' and * write it into (dynamically) malloced buffer as "ASCII" format. * * "ASCII" format means: * '\0' is written as '\\' '\0' * '\\' is written as '\\' '\\' * End of buffer is written as '\0' * * INPUTS * FILE *fp - file descriptor * int size - size of the buffer used within this function * * RESULT * char* - malloced buffer * * SEE ALSO * uti/io/sge_string2bin() * * NOTES * MT-NOTE: sge_bin2string() is MT safe ******************************************************************************/ char *sge_bin2string(FILE *fp, int size) { int i, fd; char inbuf[BUFFER], outbuf[2*BUFFER]; char *inp, *outp; char *dstbuf; int len, /* length of current tmp buffer */ dstbuflen, /* total length of destination buffer */ chunksize, /* chunks for realloc */ lastpos, /* last position in destination buffer */ error; if ((fd = fileno(fp)) == -1) return NULL; chunksize = 20480; if (size <= 0) /* no idea about buffer, malloc in chunks */ size = chunksize; dstbuf = (char *) malloc(size+1); dstbuflen = size; lastpos = 0; error = false; while (!error) { i = read(fd, inbuf, BUFFER); if (i > 0) { inp = inbuf; outp = outbuf; while (inp < &inbuf[i]) { if (*inp == '\\') { *outp++ = '\\'; *outp++ = '\\'; } else if (*inp == '\0') { *outp++ = '\\'; *outp++ = '0'; } else *outp++ = *inp; inp++; } len = outp - outbuf; if (lastpos + len > dstbuflen) { if ((dstbuf = sge_realloc(dstbuf, lastpos + len + chunksize, 0)) == NULL) { error = true; break; } dstbuflen = lastpos + len + chunksize; } memcpy(&dstbuf[lastpos], outbuf, len); lastpos += len; } else if (i == 0) { break; } else { if (errno != EINTR) { error=true; break; } } } if (error) { free(dstbuf); return NULL; } else { if ((dstbuf = sge_realloc(dstbuf, lastpos + 1, 0)) == NULL) { return NULL; } dstbuf[lastpos] = '\0'; return dstbuf; } } /****** uti/io/sge_string2bin() *********************************************** * NAME * sge_string2bin() -- Write 'binary' string into file * * SYNOPSIS * int sge_string2bin(FILE *fp, const char *buf) * * FUNCTION * Write 'binary' string into file * * INPUTS * FILE *fp - file descriptor * const char *buf - "ASCII" string (see sge_bin2string()) * * RESULT * int - error state * 0 - OK * -1 - Error * * SEE ALSO * uti/io/sge_bin2string() * * NOTES * MT-NOTE: sge_string2bin() is MT safe ******************************************************************************/ int sge_string2bin(FILE *fp, const char *buf) { char outbuf[BUFFER]; char *outp; int fd; if ((fd = fileno(fp)) == -1) return -1; if (!buf) return -1; while (*buf) { outp = outbuf; while (*buf && (outp - outbuf < BUFFER)) { if (*buf == '\\') { if (*(buf+1) == '\\') *outp++ = '\\'; else *outp++ = '\0'; buf+=2; } else *outp++ = *buf++; } if (write(fd, outbuf, outp - outbuf) != outp - outbuf) return -1; } return 0; } /****** uti/io/sge_file2string() ********************************************** * NAME * sge_file2string() -- Load file into string * * SYNOPSIS * char* sge_file2string(const char *fname, int *len) * * FUNCTION * Load file into string. Returns a pointer to a string buffer containing * the file contents and the size of the buffer (= number of bytes read) * in the variable len. * If the file cannot be read (doesn't exist, permissions etc.), NULL is * returned as buffer and len is set to 0. * * INPUTS * const char *fname - filename * int *len - number of bytes read * * RESULT * char* - malloced string buffer * * SEE ALSO * uti/io/sge_string2file() * uti/io/sge_stream2string() * * NOTES * MT-NOTE: sge_file2string() is MT safe ******************************************************************************/ char *sge_file2string(const char *fname, int *len) { FILE *fp; SGE_STRUCT_STAT statbuf; int size, i; char *str; DENTER(CULL_LAYER, "sge_file2string"); /* initialize len - in case of errors we want to return 0 * JG: TODO: it would be better to return -1. Check if calling * functions would handle this situation. */ if (len != NULL) { *len = 0; } /* try file access, read file info */ if (SGE_STAT(fname, &statbuf)) { DEXIT; return NULL; } size = statbuf.st_size; if ((fp = fopen(fname, "r")) == NULL) { ERROR((SGE_EVENT, MSG_FILE_FOPENFAILED_SS, fname, strerror(errno))); DEXIT; return NULL; } if ((str = malloc(size+1)) == NULL) { FCLOSE(fp); DEXIT; return NULL; } str[0] = '\0'; /* ** With fread(..., size, 1, ...), ** Windows cannot read bytes here, because in ** text mode the trailing ^Z is ignored. ** CRLF -> LF conversion reduces size even further. ** Therefore, the file has less than size-1 bytes if read ** in text (ascii) mode. ** Correctly, fread returns 0, because 0 elements of ** size were read. */ if (size > 0) { #ifdef WIN32 /* fread call and evaluation of return value is different */ i = fread(str, 1, size, fp); if (i == 0) { free(str); FCLOSE(fp); DEXIT; return NULL; } str[i] = '\0'; /* delimit this string */ if (len != NULL) { *len = i; } #else i = fread(str, size, 1, fp); if (i != 1) { ERROR((SGE_EVENT, MSG_FILE_FREADFAILED_SS, fname, strerror(errno))); free(str); FCLOSE(fp); DEXIT; return NULL; } str[size] = '\0'; /* delimit this string */ if (len != NULL) { *len = size; } #endif } FCLOSE(fp); DEXIT; return str; FCLOSE_ERROR: DEXIT; return NULL; } /****** uti/io/sge_stream2string() ******************************************** * NAME * sge_stream2string() -- Read string from stream * * SYNOPSIS * char* sge_stream2string(FILE *fp, int *len) * * FUNCTION * Read string from stream * * INPUTS * FILE *fp - file descriptor * int *len - number of bytes read * * RESULT * char* - pointer to malloced string buffer * * SEE ALSO * uti/io/sge_file2string() * uti/io/sge_string2file() * * NOTES * MT-NOTE: sge_stream2string() is MT safe ******************************************************************************/ char *sge_stream2string(FILE *fp, int *len) { char *str; int filled = 0; int malloced_len, i; DENTER(TOP_LAYER, "sge_stream2string"); if (!(str = malloc(FILE_CHUNK))) { DEXIT; return NULL; } malloced_len = FILE_CHUNK; /* malloced_len-filled-1 cause we reserve space for \0 termination */ while ((i = fread(&str[filled], 1, malloced_len-filled-1, fp)) > 0) { filled += i; if (malloced_len == filled+1) { str = sge_realloc(str, malloced_len + FILE_CHUNK, 0); if (str == NULL) { DEXIT; return NULL; } malloced_len += FILE_CHUNK; } if (feof(fp)) { DPRINTF(("got EOF\n")); break; } } str[filled] = '\0'; /* NULL termination */ *len = filled; DEXIT; return str; } /****** uti/io/sge_string2file() ********************************************** * NAME * sge_string2file() -- Write string into file * * SYNOPSIS * int sge_string2file(const char *str, int len, const char *fname) * * FUNCTION * Write string into file * * INPUTS * const char *str - pointer to buffer * int len - number of bytes which should be written * const char *fname - filename * * RESULT * int - error state * 0 - OK * -1 - Error * * SEE ALSO * uti/io/sge_file2string() * uti/io/sge_stream2string() * * NOTES * MT-NOTE: sge_string2file() is MT safe ******************************************************************************/ /* #define USE_FOPEN */ int sge_string2file(const char *str, int len, const char *fname) { #ifdef USE_FOPEN FILE *fp; #else int fp = -1; #endif DENTER(TOP_LAYER, "sge_string2file"); #ifdef USE_FOPEN if (!(fp = fopen(fname, "w"))) #else if (!(fp = open(fname, O_WRONLY | O_CREAT, 0666))) #endif { ERROR((SGE_EVENT, MSG_FILE_OPENFAILED_S , fname)); DEXIT; return -1; } if (!len) { len = strlen(str); } #ifdef USE_FOPEN if (fwrite(str, len, 1, fp) != 1) #else if (write(fp, str, len) != len) #endif { int old_errno = errno; ERROR((SGE_EVENT, MSG_FILE_WRITEBYTESFAILED_IS, len, fname)); #ifdef USE_FOPEN FCLOSE(fp); #else if (close(fp) != 0) { goto FCLOSE_ERROR; } #endif unlink(fname); errno = old_errno; DEXIT; return -1; } #ifdef USE_FOPEN FCLOSE(fp); #else if (close(fp) != 0) { goto FCLOSE_ERROR; } #endif DEXIT; return 0; FCLOSE_ERROR: ERROR((SGE_EVENT, MSG_FILE_FCLOSEFAILED_SS, fname, strerror(errno))); DEXIT; return -1; }