📄 sftpcontrolsocket.cpp
字号:
found=TRUE;
break;
}
}
if (found)
{
t_directory::t_direntry *direntry=new t_directory::t_direntry[dir.num-1];
int j=0;
for (int i=0;i<dir.num;i++)
{
if (dir.direntry[i].name==pData->m_FileName)
continue;
direntry[j]=dir.direntry[i];
j++;
}
delete [] dir.direntry;
dir.direntry=direntry;
dir.num--;
cache.Store(dir, bCached);
BOOL updated=FALSE;
if (m_pDirectoryListing)
if (m_pDirectoryListing->path==dir.path)
{
updated=TRUE;
SetDirectoryListing(&dir);
}
if (!updated)
if (WorkingDir.path==dir.path)
{
updated=TRUE;
m_pOwner->SetWorkingDir(&dir);
}
}
}
cache.Unlock();
}
ResetOperation(FZ_REPLY_OK);
}
}
void CSFtpControlSocket::Rename(CString oldName, CString newName, const CServerPath &path, const CServerPath &newPath)
{
LogMessage(__FILE__, __LINE__, this, FZ_LOG_DEBUG, _T("Rename(\"%s\", \"%s\", \"%s\", \"%s\") OpMode=%d OpState=%d"), oldName, newName, path.GetPath(),
newPath.GetPath(), m_Operation.nOpMode, m_Operation.nOpState);
class CRenameData : public CFtpControlSocket::t_operation::COpData
{
public:
CRenameData() {}
virtual ~CRenameData() {}
CString oldName, newName;
CServerPath path;
CServerPath newPath;
};
if (oldName != "")
{
ASSERT(newName != "");
ASSERT(!path.IsEmpty());
ASSERT(m_Operation.nOpMode == CSMODE_NONE);
ASSERT(m_Operation.nOpState == -1);
ASSERT(!m_Operation.pData);
USES_CONVERSION;
m_Operation.nOpMode = CSMODE_RENAME;
int nLen;
char *pData;
if (newPath.IsEmpty())
{
nLen = _tcslen( path.GetPath() + oldName + path.GetPath() + newName) + 2;
pData = new char[nLen];
strcpy(pData, T2CA(path.GetPath() + oldName));
strcpy(pData + _tcslen(path.GetPath() + oldName) + 1, T2CA(path.GetPath() + newName));
}
else
{
nLen = _tcslen( path.GetPath() + oldName + newPath.GetPath() + newName) + 2;
pData = new char[nLen];
strcpy(pData, T2CA(path.GetPath() + oldName));
strcpy(pData + _tcslen(path.GetPath() + oldName) + 1, T2CA(newPath.GetPath() + newName));
}
if (!m_pDataChannel->Send(SFTP_DATAID_STC_RENAME, nLen, pData))
{
delete [] pData;
DoClose();
return;
}
delete [] pData;
CRenameData *data = new CRenameData;
data->oldName = oldName;
data->newName = newName;
data->path = path;
data->newPath = newPath;
m_Operation.pData = data;
}
else
{
ASSERT(oldName == "");
ASSERT(path.IsEmpty());
ASSERT(newPath.IsEmpty());
ASSERT(m_Operation.nOpMode == CSMODE_RENAME);
ASSERT(m_Operation.pData);
if (m_bError)
{
ResetOperation(FZ_REPLY_ERROR);
return;
}
//Rename entry in cached directory
CRenameData *pData = reinterpret_cast<CRenameData *>(m_Operation.pData);
CDirectoryCache cache;
cache.Lock();
//Rename all references to the directory in the cache
if (pData->newPath.IsEmpty())
cache.Rename(pData->path, pData->oldName, pData->newName, m_CurrentServer);
BOOL bCached = TRUE;
t_directory dir;
BOOL res = cache.Lookup(pData->path, m_CurrentServer, dir);
if (!res)
bCached = FALSE;
if (!res && m_pDirectoryListing)
{
if (m_pDirectoryListing->path == pData->path)
{
dir = *m_pDirectoryListing;
res = TRUE;
}
}
t_directory WorkingDir;
BOOL bFound = m_pOwner->GetWorkingDir(&WorkingDir);
if (!res && bFound)
if (WorkingDir.path == pData->path)
{
dir = WorkingDir;
res = TRUE;
}
if (res)
{
for (int i=0; i<dir.num; i++)
if (dir.direntry[i].name == pData->oldName)
{
if (pData->newPath.IsEmpty())
{
dir.direntry[i].name = pData->newName;
dir.direntry[i].lName = pData->newName;
dir.direntry[i].lName.MakeLower();
CDirectoryCache cache;
cache.Store(dir, bCached);
BOOL updated = FALSE;
if (m_pDirectoryListing && m_pDirectoryListing->path == dir.path)
{
updated = TRUE;
SetDirectoryListing(&dir, WorkingDir.path == dir.path);
}
if (!updated)
if (WorkingDir.path == dir.path)
{
updated = TRUE;
m_pOwner->SetWorkingDir(&dir);
}
}
else
{
t_directory::t_direntry oldentry = dir.direntry[i];
for (int j = i+1; j < dir.num; j++)
{
dir.direntry[j-1] = dir.direntry[j];
}
dir.num--;
CDirectoryCache cache;
cache.Store(dir, bCached);
// If directory, delete old directory from cache
t_directory olddir;
res = cache.Lookup(pData->path, pData->oldName, m_CurrentServer, olddir);
if (res)
{
cache.Purge(olddir.path, m_CurrentServer);
t_directory newdir;
if (cache.Lookup(dir.path, m_CurrentServer, newdir))
dir = newdir;
}
BOOL updated = FALSE;
if (m_pDirectoryListing && m_pDirectoryListing->path == dir.path)
{
updated = TRUE;
SetDirectoryListing(&dir, WorkingDir.path == dir.path);
}
if (!updated)
if (WorkingDir.path == dir.path)
{
updated = TRUE;
m_pOwner->SetWorkingDir(&dir);
}
BOOL bCached = TRUE;
BOOL res = cache.Lookup(pData->newPath, m_CurrentServer, dir);
if (!res)
bCached = FALSE;
if (!res && m_pDirectoryListing)
{
if (m_pDirectoryListing->path == pData->newPath)
{
dir = *m_pDirectoryListing;
res = TRUE;
}
}
t_directory WorkingDir;
BOOL bFound = m_pOwner->GetWorkingDir(&WorkingDir);
if (!res && bFound)
if (WorkingDir.path == pData->newPath)
{
dir = WorkingDir;
res = TRUE;
}
if (res)
{
t_directory::t_direntry *direntry = new t_directory::t_direntry[dir.num + 1];
for (int i = 0; i < dir.num; i++)
direntry[i] = dir.direntry[i];
direntry[dir.num] = oldentry;
direntry[dir.num].name = pData->newName;
direntry[dir.num].lName = pData->newName;
direntry[dir.num].lName.MakeLower();
dir.num++;
delete [] dir.direntry;
dir.direntry = direntry;
CDirectoryCache cache;
cache.Store(dir, bCached);
BOOL updated = FALSE;
if (m_pDirectoryListing && m_pDirectoryListing->path == dir.path)
{
updated = TRUE;
SetDirectoryListing(&dir, WorkingDir.path == dir.path);
}
if (!updated)
if (WorkingDir.path == dir.path)
{
updated = TRUE;
m_pOwner->SetWorkingDir(&dir);
}
}
}
break;
}
}
cache.Unlock();
ResetOperation(FZ_REPLY_OK);
}
}
void CSFtpControlSocket::MakeDir(const CServerPath &path)
{
//Directory creation works like this:
//Find existing parent and create subdirs one by one
LogMessage(__FILE__, __LINE__, this,FZ_LOG_DEBUG, _T("MakeDir(\"%s\")"), path.GetPath());
class CMakeDirData : public CSFtpControlSocket::t_operation::COpData
{
public:
CMakeDirData() {}
virtual ~CMakeDirData() {}
CServerPath path;
CServerPath Current;
std::list<CString> Segments;
};
if (m_Operation.nOpState==MKD_INIT)
{
ASSERT(!path.IsEmpty());
ASSERT(m_Operation.nOpMode==CSMODE_NONE);
ASSERT(!m_Operation.pData);
m_Operation.nOpMode=CSMODE_MKDIR;
if (!m_pDataChannel->Send(SFTP_DATAID_STC_CD, path.GetParent().GetPath()))
{
DoClose();
return;
}
CMakeDirData *data=new CMakeDirData;
data->path=path;
data->Current=path.GetParent();
data->Segments.push_front(path.GetLastSegment());
m_Operation.pData=data;
m_Operation.nOpState=MKD_FINDPARENT;
}
else if (m_Operation.nOpState==MKD_FINDPARENT)
{
ASSERT(m_Operation.nOpMode==CSMODE_MKDIR);
ASSERT(path.IsEmpty());
ASSERT(m_Operation.pData);
CMakeDirData *pData=(CMakeDirData *)m_Operation.pData;
if (!m_bError)
{
m_pOwner->SetCurrentPath(pData->Current);
if (!m_pDirectoryListing)
{
CDirectoryCache cache;
t_directory dir;
BOOL res=cache.Lookup(pData->Current, m_CurrentServer, dir, TRUE);
if (res)
SetDirectoryListing(&dir);
}
m_Operation.nOpState=MKD_MAKESUBDIRS;
pData->Current.AddSubdir(pData->Segments.front());
CString Segment=pData->Segments.front();
pData->Segments.pop_front();
if (!m_pDataChannel->Send(SFTP_DATAID_STC_MKD, Segment))
{
DoClose();
return;
}
m_Operation.nOpState=MKD_CHANGETOSUBDIR;
}
else
{
if (!pData->Current.HasParent())
ResetOperation(FZ_REPLY_ERROR);
else
{
pData->Segments.push_front(pData->Current.GetLastSegment());
pData->Current=pData->Current.GetParent();
if (!m_pDataChannel->Send(SFTP_DATAID_STC_CD, pData->Current.GetPath()))
{
DoClose();
return;
}
}
}
}
else if (m_Operation.nOpState==MKD_MAKESUBDIRS)
{
if (!m_bError)
{ //Create dir entry in parent dir
CMakeDirData *pData=(CMakeDirData *)m_Operation.pData;
ASSERT(!pData->Segments.empty());
m_pOwner->SetCurrentPath(pData->Current);
pData->Current.AddSubdir(pData->Segments.front());
CString Segment=pData->Segments.front();
pData->Segments.pop_front();
if (!m_pDataChannel->Send(SFTP_DATAID_STC_MKD,Segment))
{
DoClose();
return;
}
m_Operation.nOpState=MKD_CHANGETOSUBDIR;
}
else
ResetOperation(FZ_REPLY_ERROR);
}
else if (m_Operation.nOpState==MKD_CHANGETOSUBDIR)
{
CMakeDirData *pData=(CMakeDirData *)m_Operation.pData;
if (!m_bError)
{ //Create dir entry in parent dir
CServerPath path2=pData->Current;
if (path2.HasParent())
{
CString name=path2.GetLastSegment();
path2=path2.GetParent();
CDirectoryCache cache;
cache.Lock();
BOOL bCached=TRUE;
t_directory dir;
BOOL res=cache.Lookup(path2,m_CurrentServer,dir);
if (!res)
bCached=FALSE;
if (!res && m_pDirectoryListing)
{
if (m_pDirectoryListing->path==path2)
{
dir=*m_pDirectoryListing;
res=TRUE;
}
}
t_directory WorkingDir;
BOOL bFound=m_pOwner->GetWorkingDir(&WorkingDir);
if (!res && bFound)
if (WorkingDir.path==path2)
{
dir=WorkingDir;
res=TRUE;
}
if (!res)
{
dir.path==path2;
dir.server=m_CurrentServer;
}
int i;
for (i=0; i<dir.num;i++)
if (dir.direntry[i].name==name)
{
LogMessage(__FILE__, __LINE__, this, FZ_LOG_WARNING, _T("Warning: Dir already exists in cache!"));
break;
}
if (i==dir.num)
{
t_directory::t_direntry *entries = new t_directory::t_direntry[dir.num+1];
for (i=0;i<dir.num;i++)
entries[i]=dir.direntry[i];
entries[i].name=name;
entries[i].lName=name;
entries[i].lName.MakeLower();
entries[i].dir=TRUE;
entries[i].date.hasdate=FALSE;
entries[i].size=-1;
delete [] dir.direntry;
dir.direntry=entries;
dir.num++;
cache.Store(dir, bCached);
BOOL updated=FALSE;
if (m_pDirectoryListing && m_pDirectoryListing->path==dir.path)
{
updated=TRUE;
SetDirectoryListing(&dir);
}
if (!updated)
if (WorkingDir.path==dir.path)
{
updated=TRUE;
m_pOwner->SetWorkingDir(&dir);
}
}
cache.Unlock();
}
}
//Continue operation even if MKD failed, maybe another thread did create this directory for us
if (pData->Segments.empty())
ResetOperation(FZ_REPLY_OK);
else
{
if (!m_pDataChannel->Send(SFTP_DATAID_STC_CD, pData->Current.GetPath()))
{
DoClose();
return;
}
m_Operation.nOpState=MKD_MAKESUBDIRS;
}
}
else
ASSERT(FALSE);
}
void CSFtpControlSocket::RemoveDir(CString dirname, const CServerPath &path)
{
LogMessage(__FILE__, __LINE__, this,FZ_LOG_DEBUG, _T("RemoveDir(\"%s\", \"%s\")"),dirname, path.GetPath());
class CRemoveDirData : public CSFtpControlSocket::t_operation::COpData
{
public:
CRemoveDirData() {}
virtual ~CRemoveDirData() {}
CString m_DirName;
CServerPath path;
};
if (dirname!="")
{
ASSERT(!path.IsEmpty());
ASSERT(m_Operation.nOpMode==CSMODE_NONE);
ASSERT(m_Operation.nOpState==-1);
ASSERT(!m_Operation.pData);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -