Example #1
0
int
isioFillBuffer( int fileIndex ) {
    int status, i;
    openedDataObjInp_t dataObjReadInp;
    bytesBuf_t dataObjReadOutBBuf;

    if ( debug ) {
        printf( "isioFillBuffer: %d\n", fileIndex );
    }

    i = fileIndex;
    dataObjReadOutBBuf.buf = cacheInfo[i].base;
    dataObjReadOutBBuf.len = cacheInfo[i].bufferSize;

    memset( &dataObjReadInp, 0, sizeof( dataObjReadInp ) );

    dataObjReadInp.l1descInx = openFiles[fileIndex];
    dataObjReadInp.len = cacheInfo[i].bufferSize;

    status = rcDataObjRead( Comm, &dataObjReadInp,
                            &dataObjReadOutBBuf );

    if ( debug ) {
        printf( "isioFillBuffer rcDataObjRead stat: %d\n", status );
    }
    if ( status < 0 ) {
        return status;
    }

    cacheInfo[i].ptr = cacheInfo[i].base;
    cacheInfo[i].count = status;

    return 0;
}
Example #2
0
int irods_reli_pread ( struct irods_file *file, char *data, int length, INT64_T offset )
{
	int result;
	openedDataObjInp_t request;
	bytesBuf_t       response;

	struct irods_server *server = connect_to_host(file->host);
	if(!server) return -1;

	if(!connect_to_file(server,file)) return -1;

	if(irods_reli_lseek_if_needed(file,offset)<0) return -1;

	memset(&request,0,sizeof(request));
	request.l1descInx = file->fd;
	request.len = length;

	response.buf = data;
	response.len = length;

	debug(D_IRODS,"rcDataObjRead %s %d %d",file->host,file->fd,length);
	result = rcDataObjRead(server->conn,&request,&response);
	debug(D_IRODS,"= %d",result);

	if(result<0) {
		errno = irods_reli_errno(result);
		return -1;
	}

	file->offset += result;

	return result;
}
Example #3
0
int
irods_file_read_( int *fd, void *buffer, int *size ) {
    openedDataObjInp_t dataObjReadInp;
    bytesBuf_t dataObjReadOutBBuf;
    int status;
    char *cp1;

    if ( debug ) {
        printf( "irods_file_read_\n" );
    }

    dataObjReadOutBBuf.buf = buffer;
    dataObjReadOutBBuf.len = *size;

    memset( &dataObjReadInp, 0, sizeof( dataObjReadInp ) );

    dataObjReadInp.l1descInx = *fd;
    dataObjReadInp.len = *size;

    status = rcDataObjRead( Comm, &dataObjReadInp,
                            &dataObjReadOutBBuf );

    if ( debug ) {
        printf( "irods_file_read_ rcDataObjRead stat: %d\n", status );
    }

    return status;
}
Example #4
0
int _ifuseFileCacheRead( fileCache_t *fileCache, char *buf, size_t size, off_t offset ) {
    int status, myError;

    status = _iFuseFileCacheLseek( fileCache, offset );
    if ( status < 0 ) {
        if ( ( myError = getErrno( status ) ) > 0 ) {
            return -myError;
        }
        else {
            return -ENOENT;
        }
    }

    if ( fileCache->state == NO_FILE_CACHE ) {
        iFuseConn_t *conn;
        openedDataObjInp_t dataObjReadInp;
        bytesBuf_t dataObjReadOutBBuf;
        int myError;


        bzero( &dataObjReadInp, sizeof( dataObjReadInp ) );
        dataObjReadOutBBuf.buf = buf;
        dataObjReadOutBBuf.len = size;
        dataObjReadInp.l1descInx = fileCache->iFd;
        dataObjReadInp.len = size;
        //UNLOCK_STRUCT(*fileCache);
        conn = getAndUseConnByPath( fileCache->localPath, &status );
        //LOCK_STRUCT(*fileCache);
        status = rcDataObjRead( conn->conn,
                                &dataObjReadInp, &dataObjReadOutBBuf );
        unuseIFuseConn( conn );
        if ( status < 0 ) {
            if ( ( myError = getErrno( status ) ) > 0 ) {
                return -myError;
            }
            else {
                return -ENOENT;
            }
        }
    }
    else {
        status = read( fileCache->iFd, buf, size );

        if ( status < 0 ) {
            return errno ? ( -1 * errno ) : -1;
        }
    }
    fileCache->offset += status;

    return status;
}
Example #5
0
static ssize_t irods_read(hFILE *fpv, void *buffer, size_t nbytes)
{
    hFILE_irods *fp = (hFILE_irods *) fpv;
    openedDataObjInp_t args;
    bytesBuf_t buf;
    int ret;

    memset(&args, 0, sizeof args);
    args.l1descInx = fp->descriptor;
    args.len = nbytes;

    buf.buf = buffer;
    buf.len = nbytes;

    ret = rcDataObjRead(irods.conn, &args, &buf);
    if (ret < 0) set_errno(ret);
    return ret;
}
Example #6
0
int
rsDataObjRead( rsComm_t *rsComm, openedDataObjInp_t *dataObjReadInp,
               bytesBuf_t *dataObjReadOutBBuf ) {
    int bytesRead;
    int l1descInx = dataObjReadInp->l1descInx;

    if ( l1descInx < 2 || l1descInx >= NUM_L1_DESC ) {
        rodsLog( LOG_NOTICE,
                 "rsDataObjRead: l1descInx %d out of range",
                 l1descInx );
        return SYS_FILE_DESC_OUT_OF_RANGE;
    }
    if ( L1desc[l1descInx].inuseFlag != FD_INUSE ) {
        return BAD_INPUT_DESC_INDEX;
    }

    if ( L1desc[l1descInx].remoteZoneHost != NULL ) {
        /* cross zone operation */
        dataObjReadInp->l1descInx = L1desc[l1descInx].remoteL1descInx;
        bytesRead = rcDataObjRead( L1desc[l1descInx].remoteZoneHost->conn,
                                   dataObjReadInp, dataObjReadOutBBuf );
        dataObjReadInp->l1descInx = l1descInx;
    }
    else {
        int i;
        bytesRead = l3Read( rsComm, l1descInx, dataObjReadInp->len,
                            dataObjReadOutBBuf );
        i = applyRuleForPostProcForRead( rsComm, dataObjReadOutBBuf,
                                         L1desc[l1descInx].dataObjInfo->objPath );
        if ( i < 0 ) {
            return i;
        }
    }

    return bytesRead;
}
Example #7
0
int
isioFileRead(int fileIndex, void *buffer, int maxToRead) {
   int status, i;
   int reqSize;
   char *myPtr;
   openedDataObjInp_t dataObjReadInp;
   bytesBuf_t dataObjReadOutBBuf;
   int count;
   int toMove;
   int newBufSize;

   if (debug) printf("isioFileRead: %d\n", fileIndex);

   /* If the buffer had been used for writing, flush it */
   status = isioFlush(fileIndex);
   if (status<0) return(status);

   reqSize = maxToRead;
   myPtr = buffer;
   if (cacheInfo[fileIndex].count > 0) {
      if (cacheInfo[fileIndex].count >= reqSize) {
	 memcpy(myPtr,cacheInfo[fileIndex].ptr, reqSize);
	 cacheInfo[fileIndex].ptr += reqSize;
	 cacheInfo[fileIndex].count -= reqSize;
	 return(maxToRead);
      }
      else {
	 memcpy(myPtr,cacheInfo[fileIndex].ptr, cacheInfo[fileIndex].count);
	 cacheInfo[fileIndex].ptr += cacheInfo[fileIndex].count;
	 reqSize -=  cacheInfo[fileIndex].count;
	 myPtr += cacheInfo[fileIndex].count;
	 cacheInfo[fileIndex].count = 0;
      }
   }

   newBufSize=(2*maxToRead)+8;
   i = fileIndex;

   if (cacheInfo[i].usingUsersBuffer == 'y') {
      /* previous time we used user's buffer, this time either
         allocate a new one or use their's this time too. */
      cacheInfo[i].bufferSize = 0;
   }

   if (newBufSize > cacheInfo[i].bufferSize) {
      if (newBufSize<=ISIO_MAX_BUF_SIZE) {
	 if (cacheInfo[i].usingUsersBuffer=='n') {
	    if (debug) printf("isioFileRead calling free\n");
	    free(cacheInfo[i].base);
	 }
	 if (debug) printf("isioFileRead calling malloc\n");
	 cacheInfo[i].base=(char *)malloc(newBufSize);
	 if (cacheInfo[i].base==NULL) {
	    fprintf(stderr,"Memory Allocation error\n");
	    return(0);
	 }
	 cacheInfo[i].bufferSize = newBufSize;
	 cacheInfo[i].usingUsersBuffer = 'n';
      }
      else {
         /* Use user's buffer */
	 cacheInfo[i].base=buffer;
	 cacheInfo[i].bufferSize = maxToRead;
	 cacheInfo[i].usingUsersBuffer = 'y';
      }
      cacheInfo[i].ptr=cacheInfo[i].base;
      cacheInfo[i].count = 0;
   }

   status = isioFillBuffer(fileIndex);
   if (status<0) return(status);

   if (cacheInfo[i].usingUsersBuffer=='y') {
      count = cacheInfo[fileIndex].count;
      cacheInfo[fileIndex].count = 0;
      if (debug) printf("isioFileRead return1: %d\n", count);
      return(count);
   }
   if (cacheInfo[fileIndex].count > 0) {
      toMove = reqSize;
      if (cacheInfo[fileIndex].count < reqSize) {
	 toMove=cacheInfo[fileIndex].count;
      }
      memcpy(myPtr,cacheInfo[fileIndex].ptr, toMove);
      cacheInfo[fileIndex].ptr += toMove;
      cacheInfo[fileIndex].count -= toMove;
      myPtr += toMove;
      reqSize -= toMove;
   }
   count = (void *)myPtr-buffer;
   if (debug) printf("isioFileRead return2: %d\n", count);
   return(count);

#if 0
   /* equivalent without caching */
   dataObjReadOutBBuf.buf = buffer;
   dataObjReadOutBBuf.len = maxToRead;

   memset(&dataObjReadInp, 0, sizeof (dataObjReadInp));

   dataObjReadInp.l1descInx = openFiles[fileIndex];
   dataObjReadInp.len = maxToRead;

   return(rcDataObjRead (Comm, &dataObjReadInp,
			 &dataObjReadOutBBuf));
#endif
}
    int msiobjget_irods(
        msParam_t* inRequestPath,
        msParam_t* inFileMode,
        msParam_t* inFileFlags,
        msParam_t* inCacheFilename,
        ruleExecInfo_t* rei ) {

        char *locStr;
        int mode;
        char *cacheFilename;
        char *str, *t;
        int status, bytesRead, bytesWritten;
        int destFd, i;
        rcComm_t *rcComm = NULL;

        dataObjInp_t dataObjInp;
        int objFD;
        openedDataObjInp_t dataObjReadInp;
        openedDataObjInp_t dataObjCloseInp;
        bytesBuf_t readBuf;



        RE_TEST_MACRO( "    Calling msiobjget_irods" );

        /*  check for input parameters */
        if ( inRequestPath ==  NULL ||
                strcmp( inRequestPath->type , STR_MS_T ) != 0 ||
                inRequestPath->inOutStruct == NULL ) {
            return USER_PARAM_TYPE_ERR;
        }

        if ( inFileMode ==  NULL ||
                strcmp( inFileMode->type , STR_MS_T ) != 0 ||
                inFileMode->inOutStruct == NULL ) {
            return USER_PARAM_TYPE_ERR;
        }

        if ( inFileFlags ==  NULL ||
                strcmp( inFileFlags->type , STR_MS_T ) != 0 ||
                inFileFlags->inOutStruct == NULL ) {
            return USER_PARAM_TYPE_ERR;
        }

        if ( inCacheFilename ==  NULL ||
                strcmp( inCacheFilename->type , STR_MS_T ) != 0 ||
                inCacheFilename->inOutStruct == NULL ) {
            return USER_PARAM_TYPE_ERR;
        }

        /*  coerce input to local variables */
        str = strdup( ( char * ) inRequestPath->inOutStruct );
        if ( ( t = strstr( str, ":" ) ) != NULL ) {
            locStr = t + 1;
            if ( ( t = strstr( locStr, "/" ) ) != NULL ) {
                locStr = t;
            }
            else {
                free( str );
                return USER_INPUT_FORMAT_ERR;
            }
        }

        else {
            free( str );
            return USER_INPUT_FORMAT_ERR;
        }


        cacheFilename = ( char * ) inCacheFilename->inOutStruct;
        mode  = atoi( ( char * ) inFileMode->inOutStruct );

        /* Do the processing */

        i = connectToRemoteiRODS( ( char * ) inRequestPath->inOutStruct, &rcComm );
        if ( i < 0 ) {
            printf( "msiputobj_irods: error connecting to remote iRODS: %s:%i\n",
                    ( char * ) inRequestPath->inOutStruct, i );
            free( str );
            return i;
        }


        bzero( &dataObjInp, sizeof( dataObjInp ) );
        bzero( &dataObjReadInp, sizeof( dataObjReadInp ) );
        bzero( &dataObjCloseInp, sizeof( dataObjCloseInp ) );
        bzero( &readBuf, sizeof( readBuf ) );

        dataObjInp.openFlags = O_RDONLY;
        rstrcpy( dataObjInp.objPath, locStr, MAX_NAME_LEN );
        free( str );

        objFD = rcDataObjOpen( rcComm, &dataObjInp );
        if ( objFD < 0 ) {
            printf( "msigetobj_irods: Unable to open file %s:%i\n", dataObjInp.objPath, objFD );
            rcDisconnect( rcComm );
            return objFD;
        }

        destFd = open( cacheFilename, O_WRONLY | O_CREAT | O_TRUNC, mode );
        if ( destFd < 0 ) {
            status = UNIX_FILE_OPEN_ERR - errno;
            printf(
                "msigetobj_irods: open error for cacheFilename %s, status = %d",
                cacheFilename, status );
            rcDisconnect( rcComm );
            return status;
        }

        dataObjReadInp.l1descInx = objFD;
        dataObjCloseInp.l1descInx = objFD;

        readBuf.len = MAX_SZ_FOR_SINGLE_BUF;
        readBuf.buf = ( char * )malloc( readBuf.len );
        dataObjReadInp.len = readBuf.len;

        while ( ( bytesRead = rcDataObjRead( rcComm, &dataObjReadInp, &readBuf ) ) > 0 ) {
            bytesWritten = write( destFd, readBuf.buf, bytesRead );
            if ( bytesWritten != bytesRead ) {
                free( readBuf.buf );
                close( destFd );
                rcDataObjClose( rcComm, &dataObjCloseInp );
                rcDisconnect( rcComm );
                printf(
                    "msigetobj_irods: In Cache File %s bytesWritten %d != returned objLen %i\n",
                    cacheFilename, bytesWritten, bytesRead );
                return SYS_COPY_LEN_ERR;
            }
        }
        free( readBuf.buf );
        close( destFd );
        i = rcDataObjClose( rcComm, &dataObjCloseInp );
        rcDisconnect( rcComm );
        return i;

    }
Example #9
0
int
irodsReadlink (const char *path, char *buf, size_t size)
{
    int status;
    iFuseConn_t *iFuseConn = NULL;
    int l1descInx;
    dataObjInp_t dataObjOpenInp;
    openedDataObjInp_t dataObjReadInp;
    bytesBuf_t dataObjReadOutBBuf;
    char collPath[MAX_NAME_LEN];

    rodsLog (LOG_DEBUG, "irodsReadlink: %s", path);

    status = parseRodsPathStr ((char *) (path + 1), &MyRodsEnv, collPath);
    if (status < 0) {
        rodsLogError (LOG_ERROR, status,
                      "irodsReaddir: parseRodsPathStr of %s error", path);
        /* use ENOTDIR for this type of error */
        return -ENOTDIR;
    }

    iFuseConn = getAndUseConnByPath ((char *) path, &MyRodsEnv, &status);

    memset (&dataObjOpenInp, 0, sizeof (dataObjOpenInp));

    rstrcpy (dataObjOpenInp.objPath, collPath, MAX_NAME_LEN);
    dataObjOpenInp.openFlags = O_RDONLY;

    status = rcDataObjOpen (iFuseConn->conn, &dataObjOpenInp);

    if (status < 0) {
        if (isReadMsgError (status)) {
            ifuseReconnect (iFuseConn);
            status = rcDataObjOpen (iFuseConn->conn, &dataObjOpenInp);
        }
        if (status < 0) {
            rodsLog (LOG_ERROR,
                     "irodsReadlink: rcDataObjOpen of %s error. status = %d", collPath, status);
            unuseIFuseConn (iFuseConn);
            return -ENOENT;
        }
    }

    l1descInx = status;

    memset(&dataObjReadInp, 0, sizeof (dataObjReadInp));
    memset(&dataObjReadOutBBuf, 0, sizeof (bytesBuf_t));

    dataObjReadInp.l1descInx = l1descInx;
    dataObjReadInp.len = size - 1;
    status = rcDataObjRead(iFuseConn->conn, &dataObjReadInp, &dataObjReadOutBBuf);

    if (status < 0) {
        rodsLog (LOG_ERROR, "irodsReadlink: rcDataObjRead of %s error. status = %d", collPath, status);
        unuseIFuseConn (iFuseConn);
        return -ENOENT;
    }

    memcpy(buf, dataObjReadOutBBuf.buf, status);
    buf[status] = '\0';
    rcDataObjClose(iFuseConn->conn, &dataObjReadInp);
    unuseIFuseConn (iFuseConn);

    return (0);
}
Example #10
0
int main (int argc, char **argv) {
    rcComm_t           *conn = NULL;
    rodsEnv            irods_env;
    rErrMsg_t          err_msg;
    dataObjInp_t       data_obj;
    openedDataObjInp_t open_obj;
    int                open_fd;
    char    	       *new_host = NULL;
    
    int status;
    char *obj_name = NULL;
    char *buffer;
    char prog_name[255];
    size_t buf_size = DEFAULT_BUFFER_SIZE;
    int verbose = 0;
    int opt;
    unsigned long total_written = 0;
    int write_to_irods = 1;
    int server_set = 0;
    
    while ((opt = getopt(argc, argv, "b:vhrdw")) != -1) {
    	switch (opt) {
	    case 'b':
	    	buf_size = atoi(optarg);
		
		if (buf_size <= 0) {
		    error_and_exit(conn, "Error: buffer size must be greater than 0.\n");
		}
		
		break;
		
	    case 'v':
	    	verbose = 1;
		break;
		
	    case 'r':
	    	write_to_irods = 0;
		break;
		
	    case 'w':
	    	// dummy write option to be enforced later
		break;
		
	    case 'd':
	    	server_set = 1;
		break;
	    
	    case 'h':
	    	usage_and_exit(argv[0], EXIT_SUCCESS);
		break;
		
	    default:
	    	usage_and_exit(argv[0], EXIT_FAILURE);
		break;
	}
    }
    
    if (optind >= argc) {
    	fprintf(stderr, "Error: Missing iRODS file.\n");
	usage_and_exit(argv[0], EXIT_FAILURE);
    }
    
    obj_name = argv[optind];
    
    if ((buffer = malloc(buf_size)) == NULL) {
    	error_and_exit(conn, "Error: unable to set buffer to size %ld\n", buf_size);
    }
    
    // set the client name so iRODS knows what program is connecting to it
    sprintf(prog_name, "%s:%s", PACKAGE_NAME, PACKAGE_VERSION);
   
    if (verbose) {
    	fprintf(stderr, "Setting client name to: %s\n", prog_name);
    }
    
    setenv(SP_OPTION, prog_name, 1);
    
    // lets get the irods environment
    if ((status = getRodsEnv(&irods_env)) < 0) {
    	error_and_exit(conn, "Error: getRodsEnv failed with status %d:%s\n", status, get_irods_error_name(status, verbose));
    }
    
    if ((status = irods_uri_check(obj_name, &irods_env, verbose)) < 0) {
    	error_and_exit(conn, "Error: invalid uri: %s\n", obj_name);
    } else if (status > 0) {
    	server_set = 1;
    }
    
    if (verbose) {
    	fprintf(stderr, "host %s\nzone %s\nuser %s\nport %d\n",
	    irods_env.rodsHost, irods_env.rodsZone,
	    irods_env.rodsUserName, irods_env.rodsPort);
    }
    
    #if IRODS_VERSION_INTEGER && IRODS_VERSION_INTEGER >= 4001008
	init_client_api_table();
   #endif
    
    // make the irods connections
    conn = rcConnect(irods_env.rodsHost, irods_env.rodsPort,
    	    	     irods_env.rodsUserName, irods_env.rodsZone,
		     0, &err_msg);
		     
    if (!conn) {
    	print_irods_error("Error: rcConnect failed:", &err_msg);
	exit(EXIT_FAILURE);
    }
    
    #if IRODS_VERSION_INTEGER && IRODS_VERSION_INTEGER >= 4001008
	status = clientLogin(conn, "", "");
    #else
	status = clientLogin(conn);
    #endif

    if (status < 0) {
    	error_and_exit(conn, "Error: clientLogin failed with status %d:%s\n", status, get_irods_error_name(status, verbose));
    }
  
    // set up the data object
    memset(&data_obj, 0, sizeof(data_obj));
    strncpy(data_obj.objPath, obj_name, MAX_NAME_LEN);
    
    if (write_to_irods) {
    	data_obj.openFlags = O_WRONLY;
    } else {
    	data_obj.openFlags = O_RDONLY;
    }
    
    data_obj.dataSize = 0;

    // talk to server
    if (write_to_irods) {
    	if (!server_set) {
	    if ((status = rcGetHostForPut(conn, &data_obj, &new_host)) < 0) {
		error_and_exit(conn, "Error: rcGetHostForPut failed with status %d:%s\n", status, get_irods_error_name(status, verbose));
	    }

    	    choose_server(&conn, new_host, &irods_env, verbose);
	    free(new_host);
	}

	if ((open_fd = rcDataObjCreate(conn, &data_obj)) < 0) {
    	    error_and_exit(conn, "Error: rcDataObjCreate failed with status %d:%s\n", open_fd, get_irods_error_name(open_fd, verbose));
	}
    } else {
    	if (!server_set) {
	    if ((status = rcGetHostForGet(conn, &data_obj, &new_host)) < 0) {
		error_and_exit(conn, "Error: rcGetHostForGet failed with status %d:%s\n", status, get_irods_error_name(status, verbose));
	    }

    	    choose_server(&conn, new_host, &irods_env, verbose);
	    free(new_host);
	}

	if ((open_fd = rcDataObjOpen(conn, &data_obj)) < 0) {
    	    error_and_exit(conn, "Error: rcDataObjOpen failed with status %d:%s\n", open_fd, get_irods_error_name(open_fd, verbose));
	}
    }
    
    // the read/write loop    
    while (1) {
    	bytesBuf_t data_buffer;
	long read_in;
	long written_out;
	
	// set up common data elements
	memset(&open_obj, 0, sizeof(open_obj));
	open_obj.l1descInx = open_fd;
	data_buffer.buf = buffer;
	
	// time to read something
	if (write_to_irods) {
    	    read_in 	    = fread(buffer, 1, buf_size, stdin);
	    open_obj.len    = read_in;
	    data_buffer.len = open_obj.len;
	} else {
	    open_obj.len = buf_size;
	    data_buffer.len = open_obj.len;
	    
	    if ((read_in = rcDataObjRead(conn, &open_obj, &data_buffer)) < 0) {
    		error_and_exit(conn, "Error:  rcDataObjRead failed with status %ld:%s\n", read_in, get_irods_error_name(read_in, verbose));
	    }
	}
	
	if (verbose) {
	    fprintf(stderr, "%ld bytes read\n", read_in);
	}
	
	if (!read_in) break;
    
	// now try and write something
	if (write_to_irods) {
	    open_obj.len = read_in;
	    data_buffer.len = open_obj.len;

	    if ((written_out = rcDataObjWrite(conn, &open_obj, &data_buffer)) < 0) {
    		error_and_exit(conn, "Error:  rcDataObjWrite failed with status %ld\n", written_out, get_irods_error_name(written_out, verbose));
	    }
	} else {
	    written_out = fwrite(buffer, 1, read_in, stdout);
	}
	
	if (verbose) {
	    fprintf(stderr, "%ld bytes written\n", written_out);
	}
	
	total_written += written_out;
	
	if (read_in != written_out) {
	    error_and_exit(conn, "Error: write fail %ld written, should be %ld.\n", written_out, read_in);
	}
    };
    
    if (verbose) {
    	fprintf(stderr, "Total bytes written %ld\n", total_written);
    }
    
    if ((status = rcDataObjClose(conn, &open_obj)) < 0) {
    	error_and_exit(conn, "Error: rcDataObjClose failed with status %d:%s\n", status, get_irods_error_name(status, verbose));
    }
    
    rcDisconnect(conn);
    free(buffer);
    exit(EXIT_SUCCESS);
}