コード例 #1
0
ファイル: sendfile.c プロジェクト: BenjaminSchubert/rr
int main(void) {
  int filefd;
  int filefd_out;
  loff_t off = 0;

  filefd = open(token_file, O_RDWR | O_CREAT | O_TRUNC, 0600);
  filefd_out = open(token_file, O_RDWR | O_CREAT | O_TRUNC, 0600);
  write(filefd, TOKEN, TOKEN_SIZE);

  sendfile64(filefd_out, filefd, &off, TOKEN_SIZE);

  atomic_printf(
      "sendfile %zu bytes from %d to %d; off changed from 0 to %" PRId64 "\n",
      TOKEN_SIZE, filefd, filefd_out, off);
  lseek(filefd_out, 0, SEEK_SET);
  verify_token(filefd_out);

  lseek(filefd, 0, SEEK_SET);
  sendfile64(filefd_out, filefd, NULL, TOKEN_SIZE);

  atomic_printf("sendfile %zu bytes from %d to %d\n", TOKEN_SIZE, filefd,
                filefd_out);
  lseek(filefd_out, 0, SEEK_SET);
  verify_token(filefd_out);

  /* The test driver will clean up after us if the test failed
   * before this. */
  unlink(token_file);
  unlink(token_file_out);

  atomic_puts("EXIT-SUCCESS");

  return 0;
}
コード例 #2
0
ファイル: sendfile.c プロジェクト: JamesLinus/glibc-mips
/* Send COUNT bytes from file associated with IN_FD starting at OFFSET to
   descriptor OUT_FD.  */
ssize_t
sendfile (int out_fd, int in_fd, off_t *offset, size_t count)
{
  if (offset == NULL || sizeof (off_t) == sizeof (off64_t))
    return sendfile64 (out_fd, in_fd, (off64_t *) offset, count);
  else
    {
      off64_t ofs = *offset;
      ssize_t ret = sendfile64 (out_fd, in_fd, &ofs, count);
      *offset = ofs;
      return ret;
    }
}
コード例 #3
0
ファイル: sendfile.c プロジェクト: chandanr/xfsprogs-dev
static int
send_buffer(
	off64_t		offset,
	size_t		count,
	int		fd,
	long long	*total)
{
	off64_t		off = offset;
	ssize_t		bytes, bytes_remaining = count;
	int		ops = 0;

	*total = 0;
	while (count > 0) {
		bytes = sendfile64(file->fd, fd, &off, bytes_remaining);
		if (bytes == 0)
			break;
		if (bytes < 0) {
			perror("sendfile64");
			return -1;
		}
		ops++;
		*total += bytes;
		if (bytes >= bytes_remaining)
			break;
		bytes_remaining -= bytes;
	}
	return ops;
}
コード例 #4
0
ファイル: sendfile.c プロジェクト: jameshilliard/WECB-BH-GPL
ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
{
	size_t total=0;
	ssize_t ret;
	size_t hdr_len = 0;

	/*
	 * Send the header first.
	 * Use MSG_MORE to cork the TCP output until sendfile is called.
	 */

	if (header) {
		hdr_len = header->length;
		while (total < hdr_len) {
			ret = sys_send(tofd, header->data + total,hdr_len - total, MSG_MORE);
			if (ret == -1)
				return -1;
			total += ret;
		}
	}

	total = count;
	while (total) {
		ssize_t nwritten;
		do {
#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILE64)
			nwritten = sendfile64(tofd, fromfd, &offset, total);
#else
			nwritten = sendfile(tofd, fromfd, &offset, total);
#endif
		} while (nwritten == -1 && errno == EINTR);
		if (nwritten == -1) {
			if (errno == ENOSYS || errno == EINVAL) {
				/* Ok - we're in a world of pain here. We just sent
				 * the header, but the sendfile failed. We have to
				 * emulate the sendfile at an upper layer before we
				 * disable it's use. So we do something really ugly.
				 * We set the errno to a strange value so we can detect
				 * this at the upper level and take care of it without
				 * layer violation. JRA.
				 */
				errno = EINTR; /* Normally we can never return this. */
			}
			return -1;
		}
		if (nwritten == 0)
			return -1; /* I think we're at EOF here... */
		total -= nwritten;
	}
	return count + hdr_len;
}
コード例 #5
0
TEST(sys_sendfile, sendfile64) {
  TemporaryFile src_file;
  ASSERT_EQ(5, TEMP_FAILURE_RETRY(write(src_file.fd, "hello", 5)));

  TemporaryFile dst_file;

  off64_t offset = 2;
  size_t count = 2;
  ssize_t rc = sendfile64(dst_file.fd, src_file.fd, &offset, count);
  ASSERT_EQ(2, rc);
  ASSERT_EQ(4, offset);

  ASSERT_EQ(0, lseek(dst_file.fd, 0, SEEK_SET));
  char buf[3];
  buf[2] = '\0';
  ASSERT_EQ(2, TEMP_FAILURE_RETRY(read(dst_file.fd, &buf, 2)));
  ASSERT_STREQ("ll", buf);
}
コード例 #6
0
ファイル: sendfile.c プロジェクト: Nymphetaminer/dsl-n55u
ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
{
	size_t total=0;
	ssize_t ret;
	size_t hdr_len = 0;

	/*
	 * Send the header first.
	 * Use MSG_MORE to cork the TCP output until sendfile is called.
	 */

	if (header) {
		hdr_len = header->length;
		while (total < hdr_len) {
			ret = sys_send(tofd, header->data + total,hdr_len - total, MSG_MORE);
			if (ret == -1)
				return -1;
			total += ret;
		}
	}

	total = count;
	while (total) {
		ssize_t nwritten;
		do {
#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILE64)
			nwritten = sendfile64(tofd, fromfd, &offset, total);
#else
			nwritten = sendfile(tofd, fromfd, &offset, total);
#endif
		} while (nwritten == -1 && errno == EINTR);
		if (nwritten == -1)
			return -1;
		if (nwritten == 0)
			return -1; /* I think we're at EOF here... */
		total -= nwritten;
	}
	return count + hdr_len;
}
コード例 #7
0
ファイル: sendfile.c プロジェクト: Nymphetaminer/dsl-n55u
ssize_t sys_sendfile(int tofd, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count)
{
	size_t total=0;
	struct iovec hdtrl[2];
	size_t hdr_len = 0;

	if (header) {
		/* Set up the header/trailer iovec. */
		hdtrl[0].iov_base = header->data;
		hdtrl[0].iov_len = hdr_len = header->length;
	} else {
		hdtrl[0].iov_base = NULL;
		hdtrl[0].iov_len = hdr_len = 0;
	}
	hdtrl[1].iov_base = NULL;
	hdtrl[1].iov_base = 0;

	total = count;
	while (total + hdtrl[0].iov_len) {
		ssize_t nwritten;

		/*
		 * HPUX guarantees that if any data was written before
		 * a signal interrupt then sendfile returns the number of
		 * bytes written (which may be less than requested) not -1.
		 * nwritten includes the header data sent.
		 */

		do {
#if defined(HAVE_EXPLICIT_LARGEFILE_SUPPORT) && defined(HAVE_OFF64_T) && defined(HAVE_SENDFILE64)
			nwritten = sendfile64(tofd, fromfd, offset, total, &hdtrl[0], 0);
#else
			nwritten = sendfile(tofd, fromfd, offset, total, &hdtrl[0], 0);
#endif
		} while (nwritten == -1 && errno == EINTR);
		if (nwritten == -1)
			return -1;
		if (nwritten == 0)
			return -1; /* I think we're at EOF here... */

		/*
		 * If this was a short (signal interrupted) write we may need
		 * to subtract it from the header data, or null out the header
		 * data altogether if we wrote more than hdtrl[0].iov_len bytes.
		 * We change nwritten to be the number of file bytes written.
		 */

		if (hdtrl[0].iov_base && hdtrl[0].iov_len) {
			if (nwritten >= hdtrl[0].iov_len) {
				nwritten -= hdtrl[0].iov_len;
				hdtrl[0].iov_base = NULL;
				hdtrl[0].iov_len = 0;
			} else {
				/* iov_base is defined as a void *... */
				hdtrl[0].iov_base = ((char *)hdtrl[0].iov_base) + nwritten;
				hdtrl[0].iov_len -= nwritten;
				nwritten = 0;
			}
		}
		total -= nwritten;
		offset += nwritten;
	}
	return count + hdr_len;
}
コード例 #8
0
bool CClientThread::ProcessPacket(CRData *data)
{
	uchar id;
	if( data->getUChar(&id)==true )
	{
		switch(id)
		{
		case ID_GET_GAMELIST:
			{	
#ifdef CHECK_IDENT
				std::string ident;
				data->getStr(&ident);
				if(!FileServ::checkIdentity(ident))
				{
					Log("Identity check failed -1", LL_DEBUG);
					return false;
				}
#endif

				hFile=0;
				std::vector<std::wstring> games=get_maps();


				Log("Sending game list", LL_DEBUG);

				EnableNagle();

				CWData data;
				data.addUChar( ID_GAMELIST );
				data.addUInt( (unsigned int)games.size() );

				stack.Send(clientpipe, data);

				for(size_t i=0;i<games.size();++i)
				{
					std::string version;
					std::wstring udir;
					version=getFile(wnarrow(map_file(games[i]+L"\\version.uri",true,&udir)));

					if( udir!=L"" )
						games[i]+=L"|"+udir;

					std::string game=Server->ConvertToUTF8(games[i]);
					

					stack.Send(clientpipe, (char*)game.c_str(), game.size() );					
					stack.Send(clientpipe, (char*)version.c_str(), version.size() );
				}
				
				Log("done.", LL_DEBUG);

				DisableNagle();
			}break;
		case ID_GET_FILE_RESUME:
		case ID_GET_FILE:
		case ID_GET_FILE_RESUME_HASH:
			{
				std::string s_filename;
				if(data->getStr(&s_filename)==false)
					break;

#ifdef CHECK_IDENT
				std::string ident;
				data->getStr(&ident);
				if(!FileServ::checkIdentity(ident))
				{
					Log("Identity check failed -2", LL_DEBUG);
					return false;
				}
#endif

				std::wstring o_filename=Server->ConvertToUnicode(s_filename);

				_i64 start_offset=0;
				bool offset_set=data->getInt64(&start_offset);

				Log("Sending file "+Server->ConvertToUTF8(o_filename), LL_DEBUG);

				std::wstring filename=map_file(o_filename);

				Log("Mapped name: "+Server->ConvertToUTF8(filename), LL_DEBUG);

				if(filename.empty())
				{
					char ch=ID_BASE_DIR_LOST;
					int rc=SendInt(&ch, 1);

					if(rc==SOCKET_ERROR)
					{
						Log("Error: Socket Error - DBG: Send BASE_DIR_LOST -1", LL_DEBUG);
						return false;
					}
					Log("Info: Base dir lost -1", LL_DEBUG);
					break;
				}

				cmd_id=id;

				if( id==ID_GET_FILE_RESUME_HASH )
				{
					hash_func.init();
				}

#ifdef _WIN32
				if(filename.size()<2 || (filename[0]!='\\' && filename[1]!='\\' ) )
				{
					filename=L"\\\\?\\"+filename;			
				}

				if(bufmgr==NULL)
				{
					bufmgr=new CBufMgr(NBUFFERS,READSIZE);
				}
#endif
				
#ifndef LINUX
#ifndef BACKUP_SEM
				hFile=CreateFileW(filename.c_str(), FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED|FILE_FLAG_SEQUENTIAL_SCAN, NULL);
#else
				hFile=CreateFileW(filename.c_str(), FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED|FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_SEQUENTIAL_SCAN, NULL);
#endif

				if(hFile == INVALID_HANDLE_VALUE)
				{
					hFile=NULL;
#ifdef CHECK_BASE_PATH
					std::wstring basePath=map_file(getuntil(L"/",o_filename)+L"/");
					if(!isDirectory(basePath))
					{
						char ch=ID_BASE_DIR_LOST;
						int rc=SendInt(&ch, 1);
						if(rc==SOCKET_ERROR)
						{
							Log("Error: Socket Error - DBG: Send BASE_DIR_LOST", LL_DEBUG);
							return false;
						}
						Log("Info: Base dir lost", LL_DEBUG);
						break;
					}
#endif
					
					char ch=ID_COULDNT_OPEN;
					int rc=SendInt(&ch, 1);
					if(rc==SOCKET_ERROR)
					{
						Log("Error: Socket Error - DBG: Send COULDNT OPEN", LL_DEBUG);
						return false;
					}
					Log("Info: Couldn't open file", LL_DEBUG);
					break;
				}

				currfilepart=0;
				sendfilepart=0;
				sent_bytes=start_offset;

				LARGE_INTEGER filesize;
				GetFileSizeEx(hFile, &filesize);

				curr_filesize=filesize.QuadPart;

				next_checkpoint=start_offset+c_checkpoint_dist;
				if(next_checkpoint>curr_filesize)
					next_checkpoint=curr_filesize;

				if( offset_set==false || id==ID_GET_FILE_RESUME || id==ID_GET_FILE_RESUME_HASH )
				{
					CWData data;
					data.addUChar(ID_FILESIZE);
					data.addUInt64(filesize.QuadPart);

					int rc=SendInt(data.getDataPtr(), data.getDataSize());
					if(rc==SOCKET_ERROR)
					{
						Log("Error: Socket Error - DBG: SendSize", LL_DEBUG);
						CloseHandle(hFile);
						hFile=NULL;
						return false;
					}
				}

				if(filesize.QuadPart==0)
				{
					CloseHandle(hFile);
					hFile=NULL;
					break;
				}

				for(_i64 i=start_offset;i<filesize.QuadPart && stopped==false;i+=READSIZE)
				{
					bool last;
					if(i+READSIZE<filesize.QuadPart)
						last=false;
					else
					{
						last=true;
						Log("Reading last file part", LL_DEBUG);
					}

					while(bufmgr->nfreeBufffer()==0 && stopped==false)
					{
						int rc;
						SleepEx(0,true);
						rc=SendData();
						if(rc==-1)
						{
							Log("Error: Send failed in file loop -1", LL_DEBUG);
							CloseThread(hFile);
						}
						else if(rc==0)
							SleepEx(1,true);
					}

					if( stopped==false )
						ReadFilePart(hFile, i, last);

					if(FileServ::isPause() )
					{
						DWORD starttime=GetTickCount();
						while(GetTickCount()-starttime<5000)
						{
							SleepEx(500,true);

							int rc=SendData();
							if(rc==-1)
							{
								Log("Error: Send failed in file pause loop -2", LL_DEBUG);
								CloseThread(hFile);
							}
						}
					}
				}

				while(bufmgr->nfreeBufffer()!=NBUFFERS && stopped==false)
				{
					SleepEx(0,true);
					int rc;
					rc=SendData();
					
					if( rc==2 && bufmgr->nfreeBufffer()!=NBUFFERS )
					{
						Log("Error: File end and not all Buffers are free!-1", LL_WARNING);
					}

					if(rc==-1)
					{
						Log("Error: Send failed in off file loop -3", LL_DEBUG);
						CloseHandle(hFile);
						hFile=NULL;
						break;
					}
					else if(rc==0)
						SleepEx(1,true);
				}

				if( stopped==false )
				{
					Log("Closed file.", LL_DEBUG);
					CloseHandle(hFile);
					hFile=NULL;
				}
#else //LINUX
				hFile=open64(Server->ConvertToUTF8(filename).c_str(), O_RDONLY|O_LARGEFILE);
				
				if(hFile == INVALID_HANDLE_VALUE)
				{
#ifdef CHECK_BASE_PATH
					std::wstring basePath=map_file(getuntil(L"/",o_filename)+L"/");
					if(!isDirectory(basePath))
					{
						char ch=ID_BASE_DIR_LOST;
						int rc=SendInt(&ch, 1);
						if(rc==SOCKET_ERROR)
						{
							Log("Error: Socket Error - DBG: Send BASE_DIR_LOST", LL_DEBUG);
							return false;
						}
						Log("Info: Base dir lost", LL_DEBUG);
						break;
					}
#endif
					hFile=0;
					char ch=ID_COULDNT_OPEN;
					int rc=SendInt(&ch, 1);
					if(rc==SOCKET_ERROR)
					{
						Log("Error: Socket Error - DBG: Send COULDNT OPEN", LL_DEBUG);
						return false;
					}
					Log("Info: Couldn't open file", LL_DEBUG);
					break;
				}
				
				currfilepart=0;
				sendfilepart=0;
				
				struct stat64 stat_buf;
				fstat64(hFile, &stat_buf);
				
				off64_t filesize=stat_buf.st_size;
				curr_filesize=filesize;
				
				if( offset_set==false || id==ID_GET_FILE_RESUME || id==ID_GET_FILE_RESUME_HASH )
				{
					CWData data;
					data.addUChar(ID_FILESIZE);
					data.addUInt64(filesize);

					int rc=SendInt(data.getDataPtr(), data.getDataSize() );	
					if(rc==SOCKET_ERROR)
					{
						Log("Error: Socket Error - DBG: SendSize", LL_DEBUG);
						CloseHandle(hFile);
						hFile=0;
						return false;
					}
				}
				
				if(filesize==0)
				{
					CloseHandle(hFile);
					hFile=0;
					break;
				}
				
				off64_t foffset=start_offset;

				unsigned int s_bsize=8192;

				if(id==ID_GET_FILE || id==ID_GET_FILE_RESUME )
				{
					s_bsize=32768;
					next_checkpoint=curr_filesize;
				}
				else
				{
					next_checkpoint=start_offset+c_checkpoint_dist;
					if(next_checkpoint>curr_filesize)
					    next_checkpoint=curr_filesize;
				}

				char *buf=new char[s_bsize];

				bool has_error=false;
				
				while( foffset < filesize )
				{
					size_t count=(std::min)((size_t)s_bsize, (size_t)(next_checkpoint-foffset));
					if( clientpipe==NULL && ( id==ID_GET_FILE || id==ID_GET_FILE_RESUME ) )
					{
						ssize_t rc=sendfile64(int_socket, hFile, &foffset, count);
						if(rc>0)
						{
							foffset+=rc;
						}
						else
						{
							Log("Error: Reading and sending from file failed", LL_DEBUG);
							CloseHandle(hFile);
							delete []buf;
							return false;
						}
					}
					else
					{
						ssize_t rc=read(hFile, buf, count);
						if(rc>0)
						{
							rc=SendInt(buf, rc);
							if(rc==SOCKET_ERROR)
							{
								Log("Error: Sending data failed");
								CloseHandle(hFile);
								delete []buf;
								return false;
							}
							else if(id==ID_GET_FILE_RESUME_HASH)
							{
								hash_func.update((unsigned char*)buf, rc);
							}
							
							foffset+=rc;
						}
						else
						{
							Log("Error: Reading from file failed", LL_DEBUG);
							CloseHandle(hFile);
							delete []buf;
							return false;
						}
						
						if(id==ID_GET_FILE_RESUME_HASH && foffset==next_checkpoint)
						{
							hash_func.finalize();
							SendInt((char*)hash_func.raw_digest_int(), 16);
							next_checkpoint+=c_checkpoint_dist;
							if(next_checkpoint>curr_filesize)
								next_checkpoint=curr_filesize;
							
							hash_func.init();
						}
					}
					if(FileServ::isPause() )
					{
						Sleep(500);
					}
				}
				
				CloseHandle(hFile);
				delete []buf;
				hFile=0;
#endif

			}break;
		case ID_GET_FILE_BLOCKDIFF:
			{
				bool b=GetFileBlockdiff(data);
				if(!b)
					return false;
			}break;
		case ID_BLOCK_REQUEST:
			{
				if(state==CS_BLOCKHASH)
				{
					Handle_ID_BLOCK_REQUEST(data);
				}
			}break;
		}
	}
	if( stopped==true )
		return false;
	else
		return true;
}
コード例 #9
0
ファイル: vfs_so.c プロジェクト: zhangyinuo/otttt
static void do_send(int fd)
{
	LOG(glogfd, LOG_TRACE, "%s:%s:%d\n", ID, FUNC, LN);
	int ret = SEND_ADD_EPOLLIN;
	int n = 0;
	struct conn *curcon = &acon[fd];
	if (curcon->fd < 0)
	{
		LOG(glogfd, LOG_DEBUG, "fd %d already be closed %s\n", fd, FUNC);
		return;
	}
	int localfd;
	off_t start;
	char* data;
	size_t len;
	if(!mybuff_getdata(&(curcon->send_buff), &data, &len)) 
	{
		LOG(glogfd, LOG_TRACE, "fd[%d] get len from data [%d]\n", fd, len);
		while (1)
		{
			n = send(fd, data, len, MSG_DONTWAIT | MSG_NOSIGNAL);
			if(n > 0) 
			{
				LOG(glogfd, LOG_NORMAL, "fd[%d] send len %d, datalen %d\n", fd, n, len);
				mybuff_skipdata(&(curcon->send_buff), n);
				if (n < len)
					ret = SEND_ADD_EPOLLOUT;
				curcon->send_len += n;
			}
			else if(errno == EINTR) 
				continue;
			else if(errno == EAGAIN) 
				ret = SEND_ADD_EPOLLOUT;
			else
			{
				LOG(glogfd, LOG_ERROR, "%s:%s:%d fd[%d] send err %d:%d:%m\n", ID, FUNC, LN, fd, n, len);
				ret = SEND_CLOSE;
			}
			break;
		}
	}
	if(ret == SEND_ADD_EPOLLIN && !mybuff_getfile(&(curcon->send_buff), &localfd, &start, &len))
	{
		LOG(glogfd, LOG_TRACE, "fd[%d] get len from file [%d]\n", fd, len);
		size_t len1 = len > GSIZE ? GSIZE : len;
		while (1)
		{
			n = sendfile64(fd, localfd, &start, len1);
			if(n > 0) 
			{
				mybuff_skipfile(&(curcon->send_buff), n);
				LOG(glogfd, LOG_TRACE, "%s:%s:%d fd[%d] send len %d, datalen %d\n", ID, FUNC, LN, fd, n, len1);
				if(n < len) 
					ret = SEND_ADD_EPOLLOUT;
				curcon->send_len += n;
			}
			else if(errno == EINTR) 
				continue;
			else if(errno == EAGAIN || errno == ENOENT) 
				ret = SEND_ADD_EPOLLOUT;
			else 
			{
				LOG(glogfd, LOG_ERROR, "%s:%s:%d fd[%d] send err %d:%d:%m\n", ID, FUNC, LN, fd, n, len);
				ret = SEND_CLOSE;
			}
			break;
		}
	}

	switch (ret)
	{
		case SEND_CLOSE:
			do_close(fd);
			return;
		case SEND_ADD_EPOLLIN:
			modify_fd_event(fd, EPOLLIN);
			break;
		case SEND_ADD_EPOLLOUT:
			modify_fd_event(fd, EPOLLOUT);
			break;
		case SEND_ADD_EPOLLALL:
			modify_fd_event(fd, EPOLLOUT|EPOLLIN);
			break;
	}

	if (n > 0 && solib.svc_send_once)
		solib.svc_send_once(fd);

	if (ret == SEND_ADD_EPOLLIN && solib.svc_send)
		if (solib.svc_send(fd) == SEND_CLOSE)
		{
			LOG(glogfd, LOG_ERROR, "%s:%s:%d send close\n", ID, FUNC, LN);
			do_close(fd);
		}
}
コード例 #10
0
ファイル: fsUtil.cpp プロジェクト: HeapStats/heapstats
/*!
 * \brief Copy data as avoid overwriting.
 * \param sourceFile [in] Path of source file.
 * \param destPath   [in] Path of directory put duplicated file.
 * \param destName   [in] Name of duplicated file.<br>
 *                        Don't rename, if value is null.
 * \return Value is zero, if process is succeed.<br />
 *         Value is error number a.k.a. "errno", if process is failure.
 */
int copyFile(char const *sourceFile, char const *destPath,
             char const *destName) {
  char rpath[PATH_MAX];

  if (unlikely(!isCopiablePath(sourceFile, rpath))) {
    return EINVAL;
  }

  int result = 0;
  /* Make file name. */
  char *newFile = destName == NULL
                      ? createFilename(destPath, (char *)sourceFile)
                      : createFilename(destPath, (char *)destName);

  /* Failure make filename. */
  if (unlikely(newFile == NULL)) {
    logger->printWarnMsg("Couldn't allocate copy source file path.");

    /*
     * Because exist below two pattern when "createFilename" return NULL.
     * 1, Illegal argument. "errno" don't change.
     * 2, No usable memory. "errno" maybe "ENOMEM".
     */
    return (errno != 0) ? errno : EINVAL;
  }

  /* Get uniq file name. */
  char *destFile = createUniquePath(newFile, false);
  if (unlikely(destFile == NULL)) {
    logger->printWarnMsg("Couldn't allocate unique destination file name.");
    free(newFile);
    return ENOMEM;
  }

  /* Open copy source file. */
  int sourceFd = open(sourceFile, O_RDONLY);
  if (unlikely(sourceFd < 0)) {
    result = errno;
    logger->printWarnMsgWithErrno("Couldn't open copy source file.");
    free(newFile);
    free(destFile);
    return result;
  }

  /* Get source file size */
  struct stat st;
  if (unlikely(fstat(sourceFd, &st) != 0)) {
    result = errno;
    logger->printWarnMsgWithErrno("Couldn't open copy destination file.");
    free(newFile);
    free(destFile);
    close(sourceFd);
    return result;
  }

  /* Open destination file. */
  int destFd = open(destFile, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
  if (unlikely(destFd < 0)) {
    result = errno;
    logger->printWarnMsgWithErrno("Couldn't open copy destination file.");
    free(newFile);
    free(destFile);
    close(sourceFd);
    return result;
  }

  /* Copy data */
  if (st.st_size > 0) {
    if (unlikely(sendfile64(destFd, sourceFd, NULL, st.st_size) == -1)) {
      result = errno;
      logger->printWarnMsgWithErrno("Couldn't copy file.");
    }
  } else { /* This route is for files in procfs */
    char buf[1024];
    ssize_t read_size;

    while ((read_size = read(sourceFd, buf, 1024)) > 0) {
      if (write(destFd, buf, (size_t)read_size) == -1) {
        read_size = -1;
        break;
      }
    }

    if (read_size == -1) {
      result = errno;
      logger->printWarnMsgWithErrno("Couldn't copy file.");
    }
  }

  /* Clean up */
  close(sourceFd);

  if (unlikely((close(destFd) != 0) && (result == 0))) {
    result = errno;
    logger->printWarnMsgWithErrno("Couldn't write copy file data.");
  }

  free(newFile);
  free(destFile);

  return result;
}
コード例 #11
0
ファイル: TCPSocket.cpp プロジェクト: AndreGCGuerra/dune
    bool
    TCPSocket::writeFile(const char* filename, int64_t off_end, int64_t off_beg)
    {
#if defined(DUNE_OS_LINUX)
      int fd = open64(filename, O_RDONLY);
      if (fd == -1)
        return false;

      int64_t remaining = off_end;
      off64_t offset = 0;
      if (off_beg > 0)
      {
        offset = off_beg;
        remaining -= off_beg;
      }

      while (remaining >= 0)
      {
        ssize_t rv = sendfile64(m_handle, fd, &offset, c_block_size);

        if (rv == -1)
        {
          close(fd);
          return false;
        }

        remaining -= rv;
        Concurrency::Scheduler::yield();
      }

      close(fd);
      return true;

#else
      std::ifstream ifs(filename, std::ios::binary);

      int64_t remaining = off_end;
      if (off_beg > 0)
      {
        ifs.seekg(off_beg, std::ios::beg);
        if (ifs.fail())
          return false;

        remaining -= off_beg;
      }

      char bfr[c_block_size];
      int64_t rv = 0;

      while (remaining >= 0)
      {
        ifs.read(bfr, c_block_size);
        rv = write(bfr, ifs.gcount());

        if (rv == -1)
          return false;

        remaining -= rv;
      }

      return true;
#endif
    }
コード例 #12
0
ファイル: ftpprotocol.c プロジェクト: cmbug/Mftp
void do_cmd_retr(session_t *pses)
{
    //创建数据连接
    if(get_transfer_fd(pses) < 0)
        return;

    long long offset = 0;
    if(pses->restart_pos > 0)   //是否需要断点续传
    {
        offset = pses->restart_pos;
        pses->restart_pos = 0;
    }
    //打开文件
    int fd = open(pses->arg, O_RDONLY);
    if(fd < 0)
    {
        ftp_reply(pses->ctrl_fd, FTP_FILEFAIL, "Failed to open file.");
        return;
    }
    //给文件加读锁
    int iret = lock_file_read(fd);
    if(iret == -1)
    {
        ftp_reply(pses->ctrl_fd, FTP_FILEFAIL, "Failed to open file.");
        return;
    }
    //判定文件属性是否是普通文件
    struct stat sbuf;
    iret = fstat(fd, &sbuf);
    if(!S_ISREG(sbuf.st_mode))
    {
        ftp_reply(pses->ctrl_fd, FTP_FILEFAIL, "Failed to open file.");
        return;
    }

    //定位到断点
    if(offset > 0)
    {
        iret = lseek(fd, offset, SEEK_SET);
        if(iret < 0)
        {
            ftp_reply(pses->ctrl_fd, FTP_FILEFAIL, "Failed to open file.");
            return;
        }
    }
    //150 应答
    char sendbuf[1024] = {0};
    if(pses->is_ascii)
    {
        sprintf(sendbuf, "Opening ASCII mode data connection for %s (%lld bytes).",
                pses->arg, (long long)sbuf.st_size);
    }
    else
    {
        sprintf(sendbuf, "Opening BINARY mode data connection for %s (%lld bytes).",
                pses->arg, (long long)sbuf.st_size);
    }
    ftp_reply(pses->ctrl_fd, FTP_DATACONN, sendbuf);

    //传输文件
    int flag = 0;
    long long bytes_to_send = sbuf.st_size;
    if(offset > bytes_to_send)      //客户端发来的断点位置超过了文件长度
    {
        bytes_to_send = 0;
    }
    else
    {
        bytes_to_send -= offset;
    }
    //发送数据
    while(bytes_to_send > 0)
    {
        int num_this_time = bytes_to_send > 4096 ? 4096 : bytes_to_send;
        iret = sendfile64(pses->data_fd, fd, NULL, num_this_time);
        if(iret < 0)
        {
            flag = -2;
            break;
        }
        bytes_to_send -= iret;
    }
    //发送成功
    if(bytes_to_send == 0)
    {
        flag = 0;
    }
    //关闭数据套接字
    close(pses->data_fd);
    pses->data_fd = -1;

    //关闭文件
    unlock_file(fd);
    close(fd);

    if(flag == 0)
    {
        //226
        ftp_reply(pses->ctrl_fd, FTP_TRANSFEROK, "Transfer complete.");
    }
    else if(flag == -2)
    {
        //451
        ftp_reply(pses->ctrl_fd, FTP_BADSENDNET, "Failure writting to network stream.");
    }
}