Files
doris/be/src/rpc/file_utils.cpp
李超勇 6486be64c3 fix license statement (#29)
* change picture to word

* change picture to word

* SHOW FULL TABLES WHERE Table_type != VIEW sql can not execute

* change license description
2017-08-18 19:16:23 +08:00

460 lines
13 KiB
C++

// Copyright (c) 2017, Baidu.com, Inc. All Rights Reserved
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include "compat.h"
#include "common/logging.h"
#include <iomanip>
#include <iostream>
#include <sstream>
#include <cstdio>
extern "C" {
#include <unistd.h>
#include <errno.h>
#include <pwd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/uio.h>
}
#include <boost/shared_array.hpp>
#include <boost/shared_ptr.hpp>
#include <re2/re2.h>
#include "file_utils.h"
namespace palo {
std::mutex FileUtils::ms_mutex;
bool FileUtils::read(const std::string &fname, std::string &contents) {
off_t len {};
char *buf = file_to_buffer(fname, &len);
if (buf != 0) {
contents.append(buf, len);
delete [] buf;
return true;
}
return false;
}
ssize_t FileUtils::read(int fd, void *vptr, size_t n) {
size_t nleft = 0;
ssize_t nread = 0;
char *ptr = 0;
ptr = (char *)vptr;
nleft = n;
while (nleft > 0) {
if ((nread = ::read(fd, ptr, nleft)) < 0) {
if (errno == EINTR)
nread = 0;/* and call read() again */
else if (errno == EAGAIN)
break;
else
return -1;
}
else if (nread == 0)
break; /* EOF */
nleft -= nread;
ptr += nread;
}
return n - nleft;
}
ssize_t FileUtils::pread(int fd, void *vptr, size_t n, off_t offset) {
size_t nleft = 0;
ssize_t nread = 0;
char *ptr = 0;
ptr = (char *)vptr;
nleft = n;
while (nleft > 0) {
if ((nread = ::pread(fd, ptr, nleft, offset)) < 0) {
if (errno == EINTR)
nread = 0;/* and call read() again */
else if (errno == EAGAIN)
break;
else
return -1;
}
else if (nread == 0)
break; /* EOF */
nleft -= nread;
ptr += nread;
offset += nread;
}
return n - nleft;
}
ssize_t FileUtils::write(const std::string &fname, const std::string &contents) {
int fd = open(fname.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd < 0) {
int saved_errno = errno;
LOG(ERROR) << "Unable to open file \"%s\" for writing - %s" << fname.c_str() <<
strerror(saved_errno);
errno = saved_errno;
return -1;
}
ssize_t rval = write(fd, contents);
::close(fd);
return rval;
}
ssize_t FileUtils::write(int fd, const void *vptr, size_t n) {
size_t nleft = 0;
ssize_t nwritten = 0;
const char *ptr = 0;
ptr = (const char *)vptr;
nleft = n;
while (nleft > 0) {
if ((nwritten = ::write(fd, ptr, nleft)) <= 0) {
if (errno == EINTR)
nwritten = 0; /* and call write() again */
else if (errno == EAGAIN)
break;
else
return -1; /* error */
}
nleft -= nwritten;
ptr += nwritten;
}
return n - nleft;
}
ssize_t FileUtils::writev(int fd, const struct iovec *vector, int count) {
ssize_t nwritten = 0;
while ((nwritten = ::writev(fd, vector, count)) <= 0) {
if (errno == EINTR)
nwritten = 0; /* and call write() again */
else if (errno == EAGAIN) {
nwritten = 0;
break;
}
else
return -1; /* error */
}
return nwritten;
}
ssize_t FileUtils::sendto(int fd, const void *vptr, size_t n,
const sockaddr *to, socklen_t tolen) {
size_t nleft = 0;
ssize_t nsent = 0;
const char *ptr = 0;
ptr = (const char *)vptr;
nleft = n;
while (nleft > 0) {
if ((nsent = ::sendto(fd, ptr, nleft, 0, to, tolen)) <= 0) {
if (errno == EINTR)
nsent = 0; /* and call sendto() again */
else if (errno == EAGAIN || errno == ENOBUFS)
break;
else
return -1; /* error */
}
nleft -= nsent;
ptr += nsent;
}
return n - nleft;
}
ssize_t FileUtils::send(int fd, const void *vptr, size_t n) {
size_t nleft = 0;
ssize_t nsent = 0 ;
const char *ptr = 0;
ptr = (const char *)vptr;
nleft = n;
while (nleft > 0) {
if ((nsent = ::send(fd, ptr, nleft, 0)) <= 0) {
if (errno == EINTR)
nsent = 0; /* and call sendto() again */
else if (errno == EAGAIN || errno == ENOBUFS)
break;
else
return -1; /* error */
}
nleft -= nsent;
ptr += nsent;
}
return n - nleft;
}
ssize_t FileUtils::recvfrom(int fd, void *vptr, size_t n, sockaddr *from,
socklen_t *fromlen) {
ssize_t nread = 0;
while (true) {
if ((nread = ::recvfrom(fd, vptr, n, 0, from, fromlen)) < 0) {
if (errno != EINTR)
break;
}
else
break;
}
return nread;
}
ssize_t FileUtils::recv(int fd, void *vptr, size_t n) {
ssize_t nread = 0;
while (true) {
if ((nread = ::recv(fd, vptr, n, 0)) < 0) {
if (errno != EINTR)
break;
}
else
break;
}
return nread;
}
bool FileUtils::set_flags(int fd, int flags) {
int val = 0;
bool ret = true;
if ((val = fcntl(fd, F_GETFL, 0)) < 0) {
int saved_errno = errno;
LOG(ERROR) << "fcnt(F_GETFL) failed : " << ::strerror(saved_errno);
errno = saved_errno;
ret = false;
}
val |= flags;
if (fcntl(fd, F_SETFL, val) < 0) {
int saved_errno = errno;
LOG(ERROR) << "fcnt(F_SETFL) failed : " << ::strerror(saved_errno);
errno = saved_errno;
ret = false;
}
return ret;
}
char *FileUtils::file_to_buffer(const std::string &fname, off_t *lenp) {
struct stat statbuf;
int fd= -1;
*lenp = 0;
if ((fd = open(fname.c_str(), O_RDONLY)) < 0) {
int saved_errno = errno;
LOG(ERROR) << "open(\"%s\") failure - %s" << fname.c_str() <<
strerror(saved_errno);
errno = saved_errno;
return 0;
}
if (fstat(fd, &statbuf) < 0) {
int saved_errno = errno;
LOG(ERROR) << "fstat(\"%s\") failure - %s" << fname.c_str() <<
strerror(saved_errno);
errno = saved_errno;
return 0;
}
*lenp = statbuf.st_size;
char *rbuf = new char [*lenp + 1];
ssize_t nread = FileUtils::read(fd, rbuf, *lenp);
::close(fd);
if (nread == (ssize_t)-1) {
int saved_errno = errno;
LOG(ERROR) << "read(\"%s\") failure - %s" << fname.c_str() <<
strerror(saved_errno);
errno = saved_errno;
delete [] rbuf;
*lenp = 0;
return 0;
}
if (nread < *lenp) {
LOG(WARNING) << "short read (%d of %d bytes)" << (int)nread << (int)*lenp;
*lenp = nread;
}
rbuf[nread] = 0;
return rbuf;
}
std::string FileUtils::file_to_string(const std::string &fname) {
std::string str;
off_t len;
char *contents = file_to_buffer(fname, &len);
str = (contents == 0) ? "" : contents;
delete [] contents;
return str;
}
void *FileUtils::mmap(const std::string &fname, off_t *lenp) {
int fd = -1;
struct stat statbuf;
void* map = 0;
if (::stat(fname.c_str(), &statbuf) != 0)
LOG(FATAL) << "Unable determine length of '%s' for memory mapping - %s" <<
fname.c_str() << strerror(errno);
*lenp = (off_t)statbuf.st_size;
if ((fd = ::open(fname.c_str(), O_RDONLY)) == -1)
LOG(FATAL) << "Unable to open '%s' for memory mapping - %s" << fname.c_str()
<< strerror(errno);
if ((map = ::mmap(0, *lenp, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED)
LOG(FATAL) << "Unable to memory map file '%s' - %s" << fname.c_str() <<
strerror(errno);
close(fd);
return map;
}
bool FileUtils::mkdirs(const std::string &dirname) {
struct stat statbuf;
boost::shared_array<char> tmp_dir(new char [dirname.length() + 1]);
char *tmpdir = tmp_dir.get();
char *ptr = tmpdir + 1;
strcpy(tmpdir, dirname.c_str());
while ((ptr = strchr(ptr, '/')) != 0) {
*ptr = 0;
if (stat(tmpdir, &statbuf) != 0) {
if (errno == ENOENT) {
if (mkdir(tmpdir, 0755) != 0) {
int saved_errno = errno;
LOG(ERROR) << "Problem creating directory '%s' - %s" << tmpdir
<< strerror(saved_errno);
errno = saved_errno;
return false;
}
}
else {
int saved_errno = errno;
LOG(ERROR) << "Problem stat'ing directory '%s' - %s" << tmpdir
<< strerror(saved_errno);
errno = saved_errno;
return false;
}
}
*ptr++ = '/';
}
if (stat(tmpdir, &statbuf) != 0) {
if (errno == ENOENT) {
if (mkdir(tmpdir, 0755) != 0) {
int saved_errno = errno;
LOG(ERROR) << "Problem creating directory '%s' - %s" << tmpdir
<< strerror(saved_errno);
errno = saved_errno;
return false;
}
}
else {
int saved_errno = errno;
LOG(ERROR) << "Problem stat'ing directory '%s' - %s" << tmpdir
<< strerror(saved_errno);
errno = saved_errno;
return false;
}
}
return true;
}
bool FileUtils::exists(const std::string &fname) {
struct stat statbuf;
if (stat(fname.c_str(), &statbuf) != 0)
return false;
return true;
}
bool FileUtils::unlink(const std::string &fname) {
if (::unlink(fname.c_str()) == -1) {
int saved_errno = errno;
LOG(ERROR) << "unlink(\"%s\") failed - %s" << fname.c_str()
<< strerror(saved_errno);
errno = saved_errno;
return false;
}
return true;
}
bool FileUtils::rename(const std::string &oldpath, const std::string &newpath) {
if (::rename(oldpath.c_str(), newpath.c_str()) == -1) {
int saved_errno = errno;
LOG(ERROR) << "rename(\"%s\", \"%s\") failed - %s"
<< oldpath.c_str() << newpath.c_str() << strerror(saved_errno);
errno = saved_errno;
return false;
}
return true;
}
uint64_t FileUtils::size(const std::string &fname) {
struct stat statbuf;
if (stat(fname.c_str(), &statbuf) != 0)
return 0;
return statbuf.st_size;
}
off_t FileUtils::length(const std::string &fname) {
struct stat statbuf;
if (stat(fname.c_str(), &statbuf) != 0)
return (off_t)-1;
return statbuf.st_size;
}
void FileUtils::add_trailing_slash(std::string &path) {
if (path.find('/', path.length() - 1) == std::string::npos)
path += "/";
}
bool FileUtils::expand_tilde(std::string &fname) {
if (fname[0] != '~')
return false;
std::lock_guard<std::mutex> lock(ms_mutex);
struct passwd pbuf;
struct passwd *prbuf;
char buf[256];
if (fname.length() == 1 || fname[1] == '/') {
if (getpwuid_r(getuid() , &pbuf, buf, 256, &prbuf) != 0 || prbuf == 0) {
return false;
}
fname = (std::string)pbuf.pw_dir + fname.substr(1);
}
else {
std::string name;
size_t first_slash = fname.find_first_of('/');
if (first_slash == std::string::npos) {
name = fname.substr(1);
} else {
name = fname.substr(1, first_slash-1);
}
if (getpwnam_r(name.c_str() , &pbuf, buf, 256, &prbuf) != 0 || prbuf == 0) {
return false;
}
if (first_slash == std::string::npos) {
fname = pbuf.pw_dir;
} else {
fname = (std::string)pbuf.pw_dir + fname.substr(first_slash);
}
}
return true;
}
void FileUtils::readdir(const std::string &dirname, const std::string &fname_regex,
std::vector<struct dirent> &listing) {
int ret = 0;
DIR *dirp = opendir(dirname.c_str());
struct dirent de;
struct dirent *dep = 0;
boost::shared_ptr<re2::RE2> regex(fname_regex.length()
? new re2::RE2(fname_regex)
: 0);
do {
if ((ret = readdir_r(dirp, &de, &dep)) != 0)
LOG(FATAL) << "Problem reading directory '%s' - %s" << dirname.c_str()
<< strerror(errno);
if (dep != 0 && (!regex || RE2::FullMatch(de.d_name, *regex)))
listing.push_back(de);
} while (dep != 0);
(void)closedir(dirp);
}
}