/****************************************************************************** * Copyright (c) 2000-2019 Ericsson Telecom AB * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html ******************************************************************************/ /////////////////////////////////////////////////////////////////////////////// // // File: TCCFileIO.cc // Description: TCC Useful Functions: FileIO Functions // Rev: R36B // Prodnr: CNL 113 472 // /////////////////////////////////////////////////////////////////////////////// #include "TCCFileIO_Functions.hh" #include #include #include #include #include #include #include #include #include #include #include #include #define BUF_SIZE 512 namespace TCCFileIO__Functions { /* http://www-h.eng.cam.ac.uk/help/tpl/unix/HP/bsd_to_hpux.html contains more possible solutions. */ #if defined (SOLARIS) || defined (SOLARIS8) #define LOCK_SH 1 #define LOCK_EX 2 #define LOCK_NB 4 #define LOCK_UN 8 int flock (int fd, int op) { int i; switch (op) { case LOCK_SH: case LOCK_EX: i = lockf (fd, F_LOCK, 0); break; case LOCK_SH | LOCK_NB: case LOCK_EX | LOCK_NB: i = lockf (fd, F_TLOCK, 0); if (i == -1) if (errno == EAGAIN || errno == EACCES) errno = EWOULDBLOCK; break; case LOCK_UN: i = lockf (fd, F_ULOCK, 0); break; default: i = -1; errno = EINVAL; break; } return i; } #endif #ifdef ENABLE_CHECKING /* For storing the opened files globally. */ static std::map opened_files; #endif void f__FIO__warning (const char *pl__msg, ...) __attribute__((format(printf, 1, 2))); void f__FIO__error (const char *pl__msg, ...) __attribute__((format(printf, 1, 2))); #ifdef VERBOSE_DEBUG void f__FIO__warning (const char *pl__msg, ...) { TTCN_Logger::begin_event (TTCN_WARNING); TTCN_Logger::log_event ("TCCFileIO: "); va_list ap; va_start (ap, pl__msg); TTCN_Logger::log_event_va_list (pl__msg, ap); va_end (ap); TTCN_Logger::end_event (); } void f__FIO__error (const char *pl__msg, ...) { TTCN_Logger::begin_event (TTCN_ERROR); TTCN_Logger::log_event ("TCCFileIO: "); va_list ap; va_start (ap, pl__msg); TTCN_Logger::log_event_va_list (pl__msg, ap); va_end (ap); TTCN_Logger::end_event (); } #else void f__FIO__warning (const char */*pl__msg*/, ...) { } void f__FIO__error (const char */*pl__msg*/, ...) { } #endif /* Function: f__FIO__get__error__string Returns the actual error message. Returns: The actual error message as a string. */ CHARSTRING f__FIO__get__error__string () { return CHARSTRING (strerror (errno)); } /* Function: f__FIO__get__error__code Returns the actual error code. Returns: The actual error message as a string. */ INTEGER f__FIO__get__error__code () { return INTEGER (errno); } /* Function: f__FIO__realize__error Builds the error message. (For internal use only.) Returns: Always -1. */ INTEGER f__FIO__realize__error (const char* pl__func, const char* pl__msg, const char* pl__file, const int pl__line) { f__FIO__error ("%s:%s:%s(%s:%i)",pl__func,pl__msg,strerror (errno),pl__file,pl__line); /* Always return -1 on error. */ return INTEGER (-1); } #ifdef ENABLE_CHECKING /* Function: f__FIO__opened Checks if the file with the given name is already opened. This function runs in linear time. (For internal use only.) Parameters: NAME - The name of the file. Returns: The file descriptor of the file or -1 if the file is not yet opened. */ INTEGER f__FIO__opened (const CHARSTRING& pl__name) { /* Linear time. */ for (std::map::const_iterator iter = opened_files.begin (); iter != opened_files.end (); iter++) { if ((iter->second).c_str () == pl__name) return INTEGER (iter->first); } return INTEGER (-1); } /* Function: f__FIO__opened Checks if there is a file opened with the given file descriptor. This function runs in logarithmic time. (For internal use only.) Parameters: FD - The descriptor for the file. Returns: The name of the file or an empty string if the file is not yet opened. */ CHARSTRING f__FIO__opened (const INTEGER& pl__fd) { /* Logarithmic time. */ std::map::const_iterator iter = opened_files.find (pl__fd); return (iter != opened_files.end () ? CHARSTRING ((iter->second).c_str ()) : CHARSTRING ()); } #endif /* Function: f__FIO__open Opens a file with the given name in the given mode. It creates the file if it doesn't exist. (For internal use only.) Parameters: NAME - The name of the file. FLAGS - The way to open the file. Returns: The file descriptor for the file or -1 on error. The error message is available through the f__FIO__get__error function. */ INTEGER f__FIO__open (const CHARSTRING& pl__name, const int pl__flags) { #ifdef ENABLE_CHECKING if (!(f__FIO__opened (pl__name) < 0)) return f__FIO__realize__error ("f__FIO__open", "The file is already opened", __FILE__, __LINE__); #endif int fd = open (pl__name, pl__flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); if (fd < 0) return f__FIO__realize__error ("f__FIO__open", "Cannot open file", __FILE__, __LINE__); #ifdef ENABLE_CHECKING opened_files[fd] = (const char *) pl__name; #endif return INTEGER (fd); } /* Function: f__FIO__open__rdonly A wrapper function for f__FIO__open. It opens the file with the given name for reading only. Parameters: NAME - The name of the file. Returns: What f__FIO__open returns. */ INTEGER f__FIO__open__rdonly (const CHARSTRING& pl__name) { return f__FIO__open (pl__name, O_RDONLY); } /* Function: f__FIO__open__append__wronly A wrapper function for f__FIO__open. It opens the file with the given name for writing only. If the file already exists it is opened in appending mode. Parameters: NAME - The name of the file. Returns: What f__FIO__open returns. */ INTEGER f__FIO__open__append__wronly (const CHARSTRING& pl__name) { return f__FIO__open (pl__name, O_APPEND | O_WRONLY | O_CREAT); } /* Function: f__FIO__open__append__rdwr A wrapper function for f__FIO__open. It opens the file with the given name for reading and writing. If the file already exists it is opened in appending mode. Parameters: NAME - The name of the file. Returns: What f__FIO__open returns. */ INTEGER f__FIO__open__append__rdwr (const CHARSTRING& pl__name) { return f__FIO__open (pl__name, O_APPEND | O_RDWR | O_CREAT); } /* Function: f__FIO__open__trunc__wronly A wrapper function for f__FIO__open. It opens the file with the given name for writing only. If the file was not empty it is truncated. Parameters: NAME - The name of the file. Returns: What f__FIO__open returns. */ INTEGER f__FIO__open__trunc__wronly (const CHARSTRING& pl__name) { return f__FIO__open (pl__name, O_TRUNC | O_WRONLY | O_CREAT); } /* Function: f__FIO__open__trunc__rdwr A wrapper function for f__FIO__open. It opens the file with the given name for reading and writing. If the file was not empty it is truncated. Parameters: NAME - The name of the file. Returns: What f__FIO__open returns. */ INTEGER f__FIO__open__trunc__rdwr (const CHARSTRING& pl__name) { return f__FIO__open (pl__name, O_TRUNC | O_RDWR | O_CREAT); } /* Function: f__FIO__close Closes a file associated with the given file descriptor. Parameters: FD - The file descriptor to close. Returns: What the POSIX function close returns. */ INTEGER f__FIO__close (const INTEGER& pl__fd) { #ifdef ENABLE_CHECKING std::map::iterator iter = opened_files.find (pl__fd); if (iter == opened_files.end ()) return f__FIO__realize__error ("f__FIO__close", "The file is not opened", __FILE__, __LINE__); opened_files.erase (iter); #endif return close (pl__fd); } /* Function: f__FIO__open__append__wronly__excl A wrapper function for f__FIO__open. It opens the file with the given name for writing only in exclusive mode. If the file already exists it is opened in appending mode. Parameters: NAME - The name of the file. Returns: What f__FIO__open returns or -1 if the file cannot be locked. */ INTEGER f__FIO__open__append__wronly__excl (const CHARSTRING& pl__name) { int fd = f__FIO__open (pl__name, O_APPEND | O_WRONLY | O_CREAT); if (!(fd < 0)) if (flock (fd, LOCK_EX | LOCK_NB) < 0) { f__FIO__close (fd); return f__FIO__realize__error ("f__FIO__open__append__wronly__excl", "Cannot lock file", __FILE__, __LINE__); } return fd; } /* Function: f__FIO__open__append__rdwr__excl A wrapper function for f__FIO__open. It opens the file with the given name for reading and writing in exclusive mode. If the file already exists it is opened in appending mode. Parameters: NAME - The name of the file. Returns: What f__FIO__open returns or -1 if the file cannot be locked. */ INTEGER f__FIO__open__append__rdwr__excl (const CHARSTRING& pl__name) { int fd = f__FIO__open (pl__name, O_APPEND | O_RDWR | O_CREAT); if (!(fd < 0)) if (flock (fd, LOCK_EX | LOCK_NB) < 0) { f__FIO__close (fd); return f__FIO__realize__error ("f__FIO__open__append__rdwr__excl", "Cannot lock file", __FILE__, __LINE__); } return fd; } /* Function: f__FIO__open__trunc__wronly__excl A wrapper function for f__FIO__open. It opens the file with the given name for writing only in exclusive mode. If the file was not empty it is truncated. Parameters: NAME - The name of the file. Returns: What f__FIO__open returns or -1 if the file cannot be locked. */ INTEGER f__FIO__open__trunc__wronly__excl (const CHARSTRING& pl__name) { int fd = f__FIO__open (pl__name, O_TRUNC | O_WRONLY | O_CREAT); if (!(fd < 0)) if (flock (fd, LOCK_EX | LOCK_NB) < 0) { f__FIO__close (fd); return f__FIO__realize__error ("f__FIO__open__trunc__wronly__excl", "Cannot lock file", __FILE__, __LINE__); } return fd; } /* Function: f__FIO__open__trunc__rdwr__excl A wrapper function for f__FIO__open. It opens the file with the given name for reading and writing in exclusive mode. If the file was not empty it is truncated. Parameters: NAME - The name of the file. Returns: What f__FIO__open returns or -1 if the file cannot be locked. */ INTEGER f__FIO__open__trunc__rdwr__excl (const CHARSTRING& pl__name) { int fd = f__FIO__open (pl__name, O_TRUNC | O_RDWR | O_CREAT); if (!(fd < 0)) if (flock (fd, LOCK_EX | LOCK_NB) < 0) { f__FIO__close (fd); return f__FIO__realize__error ("f__FIO__open__trunc__rdwr__excl", "Cannot lock file", __FILE__, __LINE__); } return fd; } /* Function: f__FIO__seek__home Moves the file pointer to the beginning of the file. Parameters: FD - A file descriptor. Returns: What the POSIX function lseek returns. */ INTEGER f__FIO__seek__home (const INTEGER& pl__fd) { #ifdef ENABLE_CHECKING std::map::const_iterator iter = opened_files.find ((int) pl__fd); if (iter == opened_files.end ()) return f__FIO__realize__error ("f__FIO__seek__home", "The file is not opened", __FILE__, __LINE__); #endif return lseek (pl__fd, 0, SEEK_SET); } /* Function: f__FIO__seek__end Moves the file pointer to the end of the file. Parameters: FD - A file descriptor. Returns: What the POSIX function lseek returns. */ INTEGER f__FIO__seek__end (const INTEGER& pl__fd) { #ifdef ENABLE_CHECKING std::map::const_iterator iter = opened_files.find ((int) pl__fd); if (iter == opened_files.end ()) return f__FIO__realize__error ("f__FIO__seek__end", "The file is not opened", __FILE__, __LINE__); #endif return lseek (pl__fd, 0, SEEK_END); } /* Function: f__FIO__seek__forward Moves the file pointer forward with a given number of bytes from the current position. Parameters: FD - A file descriptor. BYTES - The number of bytes. Returns: What the POSIX function lseek returns. */ INTEGER f__FIO__seek__forward (const INTEGER& pl__fd, const INTEGER& pl__bytes) { #ifdef ENABLE_CHECKING std::map::const_iterator iter = opened_files.find ((int) pl__fd); if (iter == opened_files.end ()) return f__FIO__realize__error ("f__FIO__seek__forward", "The file is not opened", __FILE__, __LINE__); #endif return lseek (pl__fd, pl__bytes, SEEK_CUR); } /* Function: f__FIO__seek__backward Moves the file pointer backward with a given number of bytes from the current position. Parameters: FD - A file descriptor. BYTES - The number of bytes. Returns: What the POSIX function lseek returns. */ INTEGER f__FIO__seek__backward (const INTEGER& pl__fd, const INTEGER& pl__bytes) { #ifdef ENABLE_CHECKING std::map::const_iterator iter = opened_files.find ((int) pl__fd); if (iter == opened_files.end ()) return f__FIO__realize__error ("f__FIO__seek__backward", "The file is not opened", __FILE__, __LINE__); #endif return lseek (pl__fd, -pl__bytes, SEEK_CUR); } /* Function: f__FIO__flush Transfers ("flushes") all modified in-core data of the file referred to by the file descriptor to the disk device. Parameters: FD - A file descriptor. Returns: What fsync returns. */ INTEGER f__FIO__flush (const INTEGER& pl__fd) { #ifdef ENABLE_CHECKING std::map::const_iterator iter = opened_files.find ((int) pl__fd); if (iter == opened_files.end ()) return f__FIO__realize__error ("f__flush", "The file is not opened", __FILE__, __LINE__); #endif return fsync ((int) pl__fd); } /* Function: f__FIO__write Writes the given data to the file associated with the given file descriptor. It works with textual and binary data. (For internal use only.) Parameters: FD - A file descriptor. DATA - The data to write to the file. Returns: The number of bytes written or -1 on error. */ template INTEGER f__FIO__write (const INTEGER& pl__fd, const T& pl__data, bool pl__flush = false) { #ifdef ENABLE_CHECKING std::map::const_iterator iter = opened_files.find ((int) pl__fd); if (iter == opened_files.end ()) return f__FIO__realize__error ("f__FIO__write", "The file is not opened", __FILE__, __LINE__); #endif int bytes = write (pl__fd, (const void *) pl__data, pl__data.lengthof ()); if (bytes < 0) return f__FIO__realize__error ("f__FIO__write", "Cannot write to file", __FILE__, __LINE__); if (pl__flush) f__FIO__flush (pl__fd); /* We can safely return here. */ return INTEGER (bytes); } /* Function: f__FIO__write__text A wrapper function for f__FIO__write. It writes textual data. Parameters: FD - A file descriptor. TEXT - The text to write to the file. Returns: What f__FIO__write returns. */ INTEGER f__FIO__write__text (const INTEGER& pl__fd, const CHARSTRING& pl__text) { return f__FIO__write (pl__fd, pl__text); } /* Function: f__FIO__write__text__flush A wrapper function for f__FIO__write. It writes textual data and calls f__FIO__flush. Parameters: FD - A file descriptor. TEXT - The text to write to the file. Returns: What f__FIO__write returns. */ INTEGER f__FIO__write__text__flush (const INTEGER& pl__fd, const CHARSTRING& pl__text) { return f__FIO__write (pl__fd, pl__text, true); } /* Function: f__FIO__write__data A wrapper function for f__FIO__write. It writes binary data. Parameters: FD - A file descriptor. DATA - The data to write to the file. Returns: What f__FIO__write returns. */ INTEGER f__FIO__write__data (const INTEGER& pl__fd, const OCTETSTRING& pl__data) { return f__FIO__write (pl__fd, pl__data); } /* Function: f__FIO__write__data__flush A wrapper function for f__FIO__write. It writes binary data and calls f__FIO__flush. Parameters: FD - A file descriptor. DATA - The data to write to the file. Returns: What f__FIO__write returns. */ INTEGER f__FIO__write__data__flush (const INTEGER& pl__fd, const OCTETSTRING& pl__data) { return f__FIO__write (pl__fd, pl__data, true); } /* Function: f__FIO__read Reads a given number of bytes to a given buffer from a file associated with the given file descriptor. (For internal use only.) Parameters: FD - A file descriptor. DATA - The buffer where the data will be stored. BYTES - The number of bytes to read. Returns: The number of bytes read or -1 if the requested number of bytes couldn't be read. */ template INTEGER f__FIO__read (const INTEGER& pl__fd, T& pl__data, const INTEGER& pl__bytes) { #ifdef ENABLE_CHECKING std::map::iterator iter = opened_files.find (pl__fd); if (iter == opened_files.end ()) return f__FIO__realize__error ("f__FIO__read", "The file is not opened", __FILE__, __LINE__); #endif int bytes = 0; U *buf = (U *) Malloc (sizeof (U) * ((int) pl__bytes)); memset (buf, 0, sizeof (U) * ((int) pl__bytes)); bytes = read (pl__fd, buf, pl__bytes); if (bytes < 0) { Free (buf); return f__FIO__realize__error ("f__FIO__read", "Read error", __FILE__, __LINE__); } pl__data = T (bytes, buf); Free (buf); return INTEGER (bytes); } /* Function: f__FIO__read__text A wrapper function for f__FIO__read. It reads textual data. Parameters: FD - A file descriptor. TEXT - The buffer for storing the text. BYTES - The number of bytes to read. Returns: What f__FIO__read returns. */ INTEGER f__FIO__read__text (const INTEGER& pl__fd, CHARSTRING& pl__text, const INTEGER& pl__bytes) { return f__FIO__read (pl__fd, pl__text, pl__bytes); } /* Function: f__FIO__read__data A wrapper function for f__FIO__read. It reads binary data. Parameters: FD - A file descriptor. DATA - The buffer for storing the data. BYTES - The number of bytes to read. Returns: What f__FIO__read returns. */ INTEGER f__FIO__read__data (const INTEGER& pl__fd, OCTETSTRING& pl__data, const INTEGER& pl__bytes) { return f__FIO__read (pl__fd, pl__data, pl__bytes); } /* Function: f__FIO__read__text__until It reads textual data until a given pattern is matched. Parameters: FD - A file descriptor. TEXT - The buffer for storing the text. SEPARATOR - The separator pattern. Returns: The number of bytes read from the file, not including the delimiter. In case of error it returns -1. */ INTEGER f__FIO__read__text__until (const INTEGER& pl__fd, CHARSTRING& pl__text, const CHARSTRING& pl__separator) { char *buf = NULL; /* For the whole line. */ char *out = NULL; char buf_tmp[BUF_SIZE + 1]; /* For reading chunks. */ unsigned int buf_size = BUF_SIZE << 1; unsigned int byte_num = 0; #ifdef ENABLE_CHECKING std::map::iterator iter = opened_files.find (pl__fd); if (iter == opened_files.end ()) return f__FIO__realize__error ("f__FIO__read__text__until", "The file is not opened", __FILE__, __LINE__); #endif while (true) { bzero (buf_tmp, BUF_SIZE); /* Try to read BUF_SIZE bytes. */ int bytes = read (pl__fd, buf_tmp, BUF_SIZE); buf_tmp[bytes] = '\0'; /* Never forget. */ if (bytes < 0) { if (buf) Free (buf); return f__FIO__realize__error ("f__FIO__read__text__until", "Read error", __FILE__, __LINE__); } else if (bytes == 0) { if (buf != NULL) Free (buf); return f__FIO__realize__error ("f__FIO__read__text__until", "End of file", __FILE__, __LINE__); } if (buf == NULL || byte_num + bytes >= buf_size) { int new_size = 2 * buf_size; char *new_buf = (char *) Realloc (buf, sizeof (char) * new_size); /* Blank it first time. */ if (new_size == BUF_SIZE << 2) bzero (new_buf, new_size); if (!new_buf) { if (buf != NULL) Free (buf); return f__FIO__realize__error ("f__FIO__read__text__until", "Cannot allocate memory", __FILE__, __LINE__); } buf = new_buf; buf_size = new_size; } memcpy (buf + byte_num, buf_tmp, bytes); byte_num += bytes; /* We always have space for the trailing '\0'. */ buf[byte_num] = '\0'; if (strlen (buf) >= strlen (pl__separator)) if (strstr (buf, pl__separator) != NULL) break; } int back = buf + byte_num - strstr (buf, pl__separator) - strlen (pl__separator); /* Ignore the characters after the delimiter. */ lseek (pl__fd, -back, SEEK_CUR); if (out == NULL) /* I miss "Calloc" a lot. */ out = (char *) Malloc (((strstr (buf, pl__separator) - buf) + 1) * sizeof (char)); int out_len = strstr (buf, pl__separator) - buf; bzero (out, out_len + 1); memcpy (out, buf, out_len); out[out_len] = '\0'; pl__text = CHARSTRING (out_len, out); Free (out); Free (buf); return out_len; } /* Function: f__FIO__read__data__until It reads binary data until a given pattern is matched. Parameters: FD - A file descriptor. TEXT - The buffer for storing the data. SEPARATOR - The separator pattern. Returns: The number of bytes read from the file, not including the delimiter. In case of error it returns -1. */ INTEGER f__FIO__read__data__until (const INTEGER& pl__fd, OCTETSTRING& pl__data, const OCTETSTRING& pl__separator) { int buf_size = BUF_SIZE; int buf_num = 0; unsigned char *buf = NULL; unsigned char c; #ifdef ENABLE_CHECKING std::map::iterator iter = opened_files.find (pl__fd); if (iter == opened_files.end ()) return f__FIO__realize__error ("f__FIO__read__data__until", "The file is not opened", __FILE__, __LINE__); #endif while (true) { int bytes = read (pl__fd, &c, 1); if (bytes < 0) { if (buf) Free (buf); /* Return -1 and print out a probably useful error message. */ return f__FIO__realize__error ("f__FIO__read__data__until", "Read error", __FILE__, __LINE__); } /* EOF is reached before we first matched the pattern. */ else if (bytes == 0) { if (buf) Free (buf); return f__FIO__realize__error ("f__FIO__read__data__until", "End of file", __FILE__, __LINE__); } if (buf == NULL || buf_num == (int) (sizeof (unsigned char) * buf_size)) { int new_size = buf_size * 2; unsigned char *new_buf = (unsigned char *) Realloc (buf, sizeof (unsigned char) * new_size); if (!new_buf) { if (buf) Free (buf); return f__FIO__realize__error ("f__FIO__read__data__until", "Cannot allocate memory", __FILE__, __LINE__); } buf = new_buf; buf_size = new_size; } buf[buf_num++] = c; if (buf_num >= pl__separator.lengthof () && !memcmp ((const unsigned char *) (buf + buf_num - pl__separator.lengthof ()), (const unsigned char *) pl__separator, pl__separator.lengthof ())) break; } pl__data = OCTETSTRING (buf_num - pl__separator.lengthof (), buf); Free (buf); return INTEGER (pl__data.lengthof ()); } /*Function: f__FIO__set__filedescriptor__previousline It sets the file descriptor to the begin of the previous line. Parameters: FD - A file descriptor. Returns: If there was no problem, then the return value will be 1. */ INTEGER f__FIO__set__filedescriptor__previousline (const INTEGER& pl__fd) { char buf_tmp[BUF_SIZE+ 1]; /* For reading chunks. */ int bytes = 0; int founded = 0; #ifdef ENABLE_CHECKING std::map::iterator iter = opened_files.find (pl__fd); if (iter == opened_files.end ()) return f__FIO__realize__error ("f__FIO__read__text__until", "The file is not opened", __FILE__, __LINE__); #endif while (true) { bzero (buf_tmp, BUF_SIZE); /* Try to read BUF_SIZE bytes. */ int length = lseek(pl__fd,0,SEEK_CUR); if (length >= BUF_SIZE){ lseek(pl__fd,-BUF_SIZE,SEEK_CUR); bytes = read (pl__fd, buf_tmp, BUF_SIZE); length = BUF_SIZE; buf_tmp[bytes] = '\0'; /* Never forget. */ } else if (length>0){ lseek(pl__fd,-length,SEEK_CUR); bytes = read (pl__fd, buf_tmp, length); buf_tmp[bytes] = '\0'; /* Never forget. */ } else if (length == 0) { return 0; } else { return -1; } int p = bytes-1; while ((buf_tmp[p] != '\n') && (p != 0) ) { p--; } if ((p != 0) && (founded == 0)) { founded++; p--; while ((buf_tmp[p] != '\n') && (p != 0) ) { p--; } if ((p != 0) && (founded == 1)) { lseek(pl__fd,-(length-p)+1,SEEK_CUR); return 1; } } if ((p != 0) && (founded == 1)) { lseek(pl__fd,-(length-p)+1,SEEK_CUR); return 1; } lseek(pl__fd,-length,SEEK_CUR); } } /* Function: f__FIO__read__data__TLV It reads binary data until a full ASN.1 TLV structure is read. Parameters: FD - A file descriptor. TEXT - The buffer for storing the data. Returns: The number of bytes read from the file. In case of error it returns -1. */ INTEGER f__FIO__read__data__TLV (const INTEGER& pl__fd, OCTETSTRING& pl__data) { unsigned char *buf = NULL; /* For the whole line. */ char buf_tmp[BUF_SIZE]; /* For reading chunks. */ unsigned int buf_size = BUF_SIZE << 1; unsigned int byte_num = 0; ASN_BER_TLV_t tlv; size_t tlvlength; #ifdef ENABLE_CHECKING std::map::iterator iter = opened_files.find (pl__fd); if (iter == opened_files.end ()) return f__FIO__realize__error ("f__FIO__read__data__TLV", "The file is not opened", __FILE__, __LINE__); #endif while (true) { /* Try to read BUF_SIZE bytes. */ int bytes = read (pl__fd, buf_tmp, BUF_SIZE); if (bytes < 0) { if (buf) Free (buf); return f__FIO__realize__error ("f__FIO__read__data__TLV", "Read error", __FILE__, __LINE__); } else if (bytes == 0) { if (buf != NULL) Free (buf); return f__FIO__realize__error ("f__FIO__read__data__TLV", "End of file", __FILE__, __LINE__); } if (buf == NULL || byte_num + bytes >= buf_size) { int new_size = 2 * buf_size; unsigned char *new_buf = (unsigned char *) Realloc (buf, sizeof (char) * new_size); /* Blank it first time. */ if (new_size == BUF_SIZE << 2) bzero (new_buf, new_size); if (!new_buf) { if (buf != NULL) Free (buf); return f__FIO__realize__error ("f__FIO__read__data__TLV", "Cannot allocate memory", __FILE__, __LINE__); } buf = new_buf; buf_size = new_size; } memcpy (buf + byte_num, buf_tmp, bytes); byte_num += bytes; /* Check for TLV structure */ if (ASN_BER_str2TLV(byte_num,buf,tlv,BER_ACCEPT_ALL)) { tlvlength = tlv.get_len(); break; } } /* Ignore the characters after the delimiter. */ lseek (pl__fd, -(byte_num - tlvlength), SEEK_CUR); pl__data = OCTETSTRING (tlvlength, buf); Free (buf); return tlvlength; } /* Function: f__FIO__chdir It changes the current directory. Parameters: NAME - The name of the new directory. Returns: Boolean value for successful or unsuccessful directory change */ BOOLEAN f__FIO__chdir(const CHARSTRING& pl__name) { if(chdir((const char *)(pl__name))) { f__FIO__realize__error ("f__FIO__chdir", "Cannot change directory", __FILE__, __LINE__); return FALSE; } else return TRUE; } /////////////////////////////////////////////////////////////////////////////// // Function: f_FIO_mkdir // // Purpose: // Create a new directory // // Parameters: // p_dir_name - *in* *charstring* - name of the directory to create // // Return Value: // boolean - indicate the successful or unsuccessful directory creation // // Errors: // In the case of unsuccessful operation the cause of the error can be // queried by the f_FIO_get_error_code, f_FIO_get_error_string functions // // Detailed description: // The path to the directory must exist, so the existence of the path // should be checked, and the missing directories should be created // recursively. // /////////////////////////////////////////////////////////////////////////////// BOOLEAN f__FIO__mkdir(const CHARSTRING& pl__dir__name) { if(mkdir((const char *)(pl__dir__name),0777)) { f__FIO__realize__error ("f_FIO_mkdir", "Cannot make a directory", __FILE__, __LINE__); return FALSE; } else return TRUE; } /////////////////////////////////////////////////////////////////////////////// // Function: f_FIO_rmdir // // Purpose: // Removes a directory // // Parameters: // p_dir_name - *in* *charstring* - name of the directory to remove // // Return Value: // boolean - indicate the successful or unsuccessful directory creation // // Errors: // In the case of unsuccessful operation the cause of the error can be // queried by the f_FIO_get_error_code, f_FIO_get_error_string functions // // Detailed description: // The directories must be empty, so the child directories should be // cleaned and deleted recursively. // /////////////////////////////////////////////////////////////////////////////// BOOLEAN f__FIO__rmdir(const CHARSTRING& pl__dir__name) { if(rmdir((const char *)(pl__dir__name))) { f__FIO__realize__error ("f__FIO__rmdir", "Cannot make a directory", __FILE__, __LINE__); return FALSE; } else return TRUE; } /////////////////////////////////////////////////////////////////////////////// // Function: f__FIO__remove // // Purpose: // Removes folder or a directory // // Parameters: // pl_file_name - *in* *charstring* - name of the folder/directory to remove // // Return Value: // boolean - indicate the successful or unsuccessful target removal // // Errors: // In the case of unsuccessful operation the cause of the error can be // queried by the f_FIO_get_error_code, f_FIO_get_error_string functions // /////////////////////////////////////////////////////////////////////////////// BOOLEAN f__FIO__remove(const CHARSTRING& pl__file__name) { if(remove((const char *)(pl__file__name))) { f__FIO__realize__error ("f__FIO__remove", "Cannot remove ", __FILE__, __LINE__); return FALSE; } else return TRUE; } /////////////////////////////////////////////////////////////////////////////// // Function: f_FIO_fileOrDirExists // // Purpose: // Checks the existence of files and directories. // // Parameters: // p_name - *in* *charstring* - name of the file or directory to check // // Return Value: // boolean - indicate the exictense of the file or diectory // // Errors: // - // // Detailed description: // - // /////////////////////////////////////////////////////////////////////////////// BOOLEAN f__FIO__fileOrDirExists(const CHARSTRING& filename ) { struct stat buffer ; if(stat( (const char *)filename, &buffer )==0) { return TRUE ; } return FALSE ; } /////////////////////////////////////////////////////////////////////////////// // Function: f_FIO_rename // // Purpose: // Renames a file. // // Parameters: // pl__old__name - *in* *charstring* - file/directory that needs to be renamed // pl__new__name - *in* *charstring* - new name of the file/directory // // Return Value: // boolean - indicate that the rename procedure was successful or not // // Errors: // In the case of unsuccessful operation the cause of the error can be // queried by the f_FIO_get_error_code, f_FIO_get_error_string functions // // Detailed description: // Permissions needed to rename the file/directory. // The file or directory, that would be renamed, should exist, otherwise it // returns false. The rename procedure fails in case of the target path is // not exist. // /////////////////////////////////////////////////////////////////////////////// BOOLEAN f__FIO__rename(const CHARSTRING& pl__old__name, const CHARSTRING& pl__new__name) { if(rename((const char *)(pl__old__name), (const char *)(pl__new__name))) { f__FIO__realize__error("f_FIO_rename", "Cannot rename the given file or directory.", __FILE__, __LINE__); return FALSE; } else return TRUE; } /////////////////////////////////////////////////////////////////////////////// // Function: f_FIO_stat // // Purpose: // Query the permissions of the file or directory. // // Parameters: // p_name - *in* *charstring* - name of the file or directory to check // p_permissions - *out* *FIO_permissions* - the permissions of the object // // Return Value: // boolean - indicate sucessfull execution // // Errors: // - // // Detailed description: // - // /////////////////////////////////////////////////////////////////////////////// BOOLEAN f__FIO__stat(const CHARSTRING& p__name, FIO__permissions& p__permissions ) { struct stat buffer; mode_t st_mode; if(stat( (const char *)p__name, &buffer )) { f__FIO__realize__error ("f__FIO__stat", "Cannot stat", __FILE__, __LINE__); return FALSE; } st_mode=buffer.st_mode; p__permissions.set__uid()=st_mode & S_ISUID; p__permissions.set__gid()=st_mode & S_ISGID; p__permissions.sticky__bit()=st_mode & S_ISVTX; p__permissions.owner__read()=st_mode & S_IRUSR; p__permissions.owner__write()=st_mode & S_IWUSR; p__permissions.owner__execute()=st_mode & S_IXUSR; p__permissions.group__read()=st_mode & S_IRGRP; p__permissions.group__write()=st_mode & S_IWGRP; p__permissions.group__execute()=st_mode & S_IXGRP; p__permissions.other__read()=st_mode & S_IROTH; p__permissions.other__write()=st_mode & S_IWOTH; p__permissions.other__execute()=st_mode & S_IXOTH; return TRUE; } /////////////////////////////////////////////////////////////////////////////// // Function: f_FIO_chmod // // Purpose: // Change the permissions of the file or directory. // // Parameters: // p_name - *in* *charstring* - name of the file or directory to check // p_permissions - *in* *FIO_permissions* - the permissions of the object // // Return Value: // boolean - indicate sucessfull execution // // Errors: // - // // Detailed description: // Change the permissions of the file or directory according to the // p_permissions. If the value of the field is: // - true: set the permission // - false: clear the permission // - omit: doesn't change the permission // /////////////////////////////////////////////////////////////////////////////// BOOLEAN f__FIO__chmod(const CHARSTRING& p__name, const FIO__permissions& p__permissions ) { struct stat buffer; mode_t st_mode; if(stat( (const char *)p__name, &buffer )) { f__FIO__realize__error ("f__FIO__chmod", "Cannot stat", __FILE__, __LINE__); return FALSE; } st_mode=buffer.st_mode; if(p__permissions.set__uid().ispresent()){ if(p__permissions.set__uid()()){ st_mode |= S_ISUID; } else { st_mode &= ~S_ISUID; } } if(p__permissions.set__gid().ispresent()){ if(p__permissions.set__gid()()){ st_mode |= S_ISGID; } else { st_mode &= ~S_ISGID; } } if(p__permissions.sticky__bit().ispresent()){ if(p__permissions.sticky__bit()()){ st_mode |= S_ISVTX; } else { st_mode &= ~S_ISVTX; } } if(p__permissions.owner__read().ispresent()){ if(p__permissions.owner__read()()){ st_mode |= S_IRUSR; } else { st_mode &= ~S_IRUSR; } } if(p__permissions.owner__write().ispresent()){ if(p__permissions.owner__write()()){ st_mode |= S_IWUSR; } else { st_mode &= ~S_IWUSR; } } if(p__permissions.owner__execute().ispresent()){ if(p__permissions.owner__execute()()){ st_mode |= S_IXUSR; } else { st_mode &= ~S_IXUSR; } } if(p__permissions.group__read().ispresent()){ if(p__permissions.group__read()()){ st_mode |= S_IRGRP; } else { st_mode &= ~S_IRGRP; } } if(p__permissions.group__write().ispresent()){ if(p__permissions.group__write()()){ st_mode |= S_IWGRP; } else { st_mode &= ~S_IWGRP; } } if(p__permissions.group__execute().ispresent()){ if(p__permissions.group__execute()()){ st_mode |= S_IXGRP; } else { st_mode &= ~S_IXGRP; } } if(p__permissions.other__read().ispresent()){ if(p__permissions.other__read()()){ st_mode |= S_IROTH; } else { st_mode &= ~S_IROTH; } } if(p__permissions.other__write().ispresent()){ if(p__permissions.other__write()()){ st_mode |= S_IWOTH; } else { st_mode &= ~S_IWOTH; } } if(p__permissions.other__execute().ispresent()){ if(p__permissions.other__execute()()){ st_mode |= S_IXOTH; } else { st_mode &= ~S_IXOTH; } } if(chmod( (const char *)p__name, st_mode )) { f__FIO__realize__error ("f__FIO__chmod", "Cannot chmod", __FILE__, __LINE__); return FALSE; } return TRUE; } INTEGER f__FIO__fileSize(const CHARSTRING& filename ) { struct stat buffer ; if(stat( (const char *)filename, &buffer )==0) { return INTEGER(buffer.st_size); } else{return INTEGER (-1);} } BOOLEAN f__FIO__fileList(const CHARSTRING& dirname, FileList& filelist) { struct dirent *pent; DIR *pdir; pdir=opendir((const char *)dirname); if(!pdir) { return FALSE; } else{ errno=0; int i=0; while((pent=readdir(pdir))) { filelist[i] = (pent->d_name); i = i+1; } closedir(pdir); if (errno){return FALSE;} return TRUE; } } FIO__FileInfo f__FIO__getFileInfo(const CHARSTRING& name) { FIO__FileType type = FIO__FileType::Unknown; FIO__FileInfo result (type, OMIT_VALUE, OMIT_VALUE, OMIT_VALUE, OMIT_VALUE, OMIT_VALUE, OMIT_VALUE, OMIT_VALUE, OMIT_VALUE, 0, 0, 0); struct stat sb; if (!f__FIO__fileOrDirExists(name)) { type = FIO__FileType::NotExists; } else { if (stat(name, &sb) == -1) { type = FIO__FileType::ErrorReadingFile; } switch (sb.st_mode & S_IFMT) { case S_IFBLK: type = FIO__FileType::BlockDevice; break; case S_IFCHR: type = FIO__FileType::CharacterDevice; break; case S_IFDIR: type = FIO__FileType::Directory; break; case S_IFIFO: type = FIO__FileType::FIFO__Pipe; break; case S_IFLNK: type = FIO__FileType::Symlink; break; case S_IFREG: type = FIO__FileType::RegularFile; break; case S_IFSOCK: type = FIO__FileType::Socket; break; default: type = FIO__FileType::Unknown; break; } } result.fileType() = type; if (type != FIO__FileType::NotExists && type != FIO__FileType::ErrorReadingFile) { result.nodeNumber() = sb.st_ino; result.mode() = sb.st_mode; result.linkCount() = sb.st_nlink; result.ownership() = sb.st_uid; result.groupId() = sb.st_gid; result.blockSize() = sb.st_blksize; result.fileSize() = sb.st_size; result.blocksAllocated() = sb.st_blocks; result.lastStatusChange().set_long_long_val(sb.st_ctime); result.lastFileAccess().set_long_long_val(sb.st_atime); result.lastFileModification().set_long_long_val(sb.st_mtime); } return result; } }