/*
 * fileio.h
 *
 *  Created on: 25.07.2010
 *      Author: ed
 */

#ifndef FILEIO_H_
#define FILEIO_H_

#include "meta.h"

#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <cstdio>
#include <unistd.h>

#ifdef HAVE_LINUX_SENDFILE
#include <sys/sendfile.h>
#endif

#ifndef O_BINARY
#define O_BINARY 0 // ignore on Unix
#endif

#ifdef HAVE_LINUX_FALLOCATE
int falloc_helper(int fd, off_t start, off_t len);
#else
#define falloc_helper(fd,start,len)
#endif

ssize_t sendfile_generic(int out_fd, int in_fd, off_t *offset, size_t count);

class Cstat : public stat
{
	bool bResult;
public:
	inline Cstat(cmstring &s) { bResult = !::stat(s.c_str(), static_cast<struct stat*>(this)); }
	inline operator bool() const { return bResult; }
};

bool FileCopy_generic(cmstring &from, cmstring &to);

// in fact, pipe&splice&splice method works about 10% but only without considering other IO costs
// with them, the benefit is neglible

//#if defined(HAVE_LINUX_SPLICE) && defined(HAVE_PREAD)
//bool FileCopy(cmstring &from, cmstring &to);
//#else
#define FileCopy(x,y) FileCopy_generic(x,y)
//#endif

bool LinkOrCopy(const mstring &from, const mstring &to);


void set_nb(int fd);

#define forceclose(fd) { while(0 != ::close(fd)) { if(errno != EINTR) break; }; fd=-1; }
#define checkforceclose(fd) if(fd>=0){ while(0 != ::close(fd)) { if(errno != EINTR) break; }; fd=-1; }


inline void checkForceFclose(FILE* &fh)
{
	if (fh)
	{
		int fd = fileno(fh);
		if (0 != ::fclose(fh) && errno != EBADF)
		{
			forceclose(fd);
		}
		fh = NULL;
	}
}

struct FILE_RAII
{
	FILE *p;
	inline FILE_RAII() : p(NULL) {}
	inline void close() { checkForceFclose(p); };
	inline ~FILE_RAII() { close(); }
private:
	FILE_RAII(const FILE_RAII&);
	FILE_RAII operator=(const FILE_RAII&);
};


void mkbasedir(const mstring & path);



#endif /* FILEIO_H_ */
