int SyncTransferThread::do_touch_local_file_with_time(QString fileName, QDateTime time) { // Linux 上可以使用 utime 或者 utimes 函数, - change file last access and modification times // Windows 上文件 SetFileTime()函数设置文件的创建时间、最近一次访问时间以及最近一次修改的时间等 // Windows 目录 两个函数GetDirTime()和SetDirTime()来实现对文件夹时间信息 // Qt 中好像是没有修改文件时间属性的方法。 int ret; QFileInfo fi(fileName); #ifdef WIN32 // method 1, ok QFile q_file(fileName); if (!q_file.open(QIODevice::ReadWrite)) { q_debug()<<"open file error:"<<q_file.errorString(); } else { int fp = q_file.handle(); struct _utimbuf ub; ub.actime = fi.lastRead().toTime_t(); ub.modtime = time.toTime_t(); ret = _futime(fp, &ub); q_debug()<<"_futime ret: "<<ret<<fileName <<strerror(ret); q_file.close(); } return 0; // method 2, english ok, chinese faild const char *filePathName = gOpt->locale_codec->fromUnicode(QDir::toNativeSeparators(fileName)).constData(); struct _utimbuf ub; ub.actime = fi.lastRead().toTime_t(); ub.modtime = time.toTime_t(); ret = _utime(filePathName, &ub); q_debug()<<"_utime ret: "<<ret<<filePathName<<fileName <<strerror(ret); return 0; // method 2, english ok, chinese faild QString appPath = QCoreApplication::applicationDirPath(); QString procFilePath = appPath + "/touch.exe"; QStringList args; args<<"-m"; args<<"-t"; args<<time.toString("yyyyMMddhhmm.ss"); args<<QDir::toNativeSeparators(fileName); q_debug()<<args; QProcess proc; proc.start(procFilePath, args); ret = proc.waitForFinished(); #else struct timeval tv[2] = {{0,0}, {0,0}}; tv[0].tv_sec = fi.lastRead().toTime_t(); tv[1].tv_sec = time.toTime_t(); ret = utimes(GlobalOption::instance()->locale_codec->fromUnicode(fileName), tv); assert(ret == 0); #endif return 0; }
int SyncTransferThread::do_download(QString remote_path, QString local_path) { qDebug() <<__FUNCTION__<<": "<<__LINE__<<":"<< __FILE__; qDebug()<< "remote_path = "<< remote_path << " , local_path = " << local_path ; int pcnt = 0 ; int rlen , wlen ; int file_size , tran_len = 0 ; LIBSSH2_SFTP_HANDLE * sftp_handle ; LIBSSH2_SFTP_ATTRIBUTES ssh2_sftp_attrib; char buff[8192] = {0}; QString currFile; sftp_handle = libssh2_sftp_open(this->ssh2_sftp, GlobalOption::instance()->remote_codec->fromUnicode(remote_path), LIBSSH2_FXF_READ, 0); if (sftp_handle == NULL) { //TODO 错误消息通知用户。 qDebug()<<"open sftp file error :"<< libssh2_sftp_last_error(this->ssh2_sftp); return -1 ; } memset(&ssh2_sftp_attrib,0,sizeof(ssh2_sftp_attrib)); libssh2_sftp_fstat(sftp_handle,&ssh2_sftp_attrib); file_size = ssh2_sftp_attrib.filesize; qDebug()<<" remote file size :"<< file_size ; currFile = local_path.right(local_path.length() - this->local_base_path.length() - 1); emit this->syncFileStarted(currFile, file_size); // 本地编码 --> Qt 内部编码 QFile q_file(local_path); if (!q_file.open(QIODevice::ReadWrite|QIODevice::Truncate)) { //TODO 错误消息通知用户。 qDebug()<<"open local file error:"<< q_file.errorString() ; } else { //read remote file and then write to local file while ((rlen = libssh2_sftp_read(sftp_handle, buff, sizeof(buff))) > 0) { wlen = q_file.write( buff, rlen ); tran_len += wlen ; qDebug()<<"Read len :"<<rlen <<" , write len: "<<wlen <<" tran len: "<<tran_len ; //my progress signal if (file_size == 0) { emit this->transfer_percent_changed(currFile, 100, tran_len, wlen); } else { pcnt = 100.0 *((double)tran_len / (double)file_size); emit this->transfer_percent_changed(currFile, pcnt, tran_len, wlen); } } q_file.flush(); q_file.close(); } libssh2_sftp_close(sftp_handle); q_debug()<<"syncDownload done."; this->do_touch_local_file_with_time(local_path, SSHFileInfo(ssh2_sftp_attrib).lastModified()); emit this->syncFileStopped(currFile, 0); return 0; }
Session::Session(std::string file) { local_file = file; QFileInfo q_file(local_file.c_str()); std::string date = q_file.absoluteDir().dirName().toStdString(); root = loadJSONFile(local_file.c_str()); loadFromJSON(); setDate(date); }
int SyncTransferThread::do_upload(QString local_path, QString remote_path) { qDebug() <<__FUNCTION__<<": "<<__LINE__<<":"<< __FILE__; qDebug()<< "remote_path = "<< remote_path << " , local_path = " << local_path ; int pcnt = 0 ; int rlen , wlen ; int file_size , tran_len = 0 ; LIBSSH2_SFTP_HANDLE * sftp_handle ; LIBSSH2_SFTP_ATTRIBUTES ssh2_sftp_attrib; char buff[5120] = {0}; QString currFile; //TODO 检查文件可写属性 sftp_handle = libssh2_sftp_open(this->ssh2_sftp, GlobalOption::instance()->remote_codec->fromUnicode(remote_path), LIBSSH2_FXF_READ|LIBSSH2_FXF_WRITE|LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC, 0666); if (sftp_handle == NULL) { //TODO 错误消息通知用户。 char errmsg[200] = {0}; int emlen = 0; libssh2_session_last_error(this->ssh2_sess, (char **)&errmsg, &emlen, 0); qDebug()<<"open sftp file error :"<< libssh2_sftp_last_error(this->ssh2_sftp) <<QString(errmsg); if (libssh2_sftp_last_error(this->ssh2_sftp) == LIBSSH2_FX_PERMISSION_DENIED) { // this->errorString = QString(tr("Open file faild, Permission denied")); // qDebug()<<this->errorString; } // this->error_code = ERRNO_BASE + libssh2_sftp_last_error(this->ssh2_sftp); emit this->syncFileStopped(currFile, -1); return -1 ; } memset(&ssh2_sftp_attrib,0,sizeof(ssh2_sftp_attrib)); QFileInfo local_fi(local_path); file_size = local_fi.size(); qDebug()<<"local file size:" << file_size ; currFile = local_path.right(local_path.length() - this->local_base_path.length() - 1); emit this->syncFileStarted(currFile, file_size); // 本地编码 --> Qt 内部编码 QFile q_file(local_path); if (!q_file.open( QIODevice::ReadOnly)) { //TODO 错误消息通知用户。 qDebug()<<"open local file error:"<< q_file.errorString() ; //printf("open local file error:%s\n", strerror( errno ) ); } else { //read local file and then write to remote file while (!q_file.atEnd()) { qDebug()<<"Read local ... "; rlen = q_file.read(buff, sizeof(buff)); qDebug()<<"Read local done "; if (rlen <= 0) { //qDebug()<<"errno: "<<errno<<" err msg:"<< strerror( errno) << ftell( local_handle) ; break ; } qDebug()<<"write to sftp ... "; wlen = libssh2_sftp_write(sftp_handle, buff, rlen); qDebug()<<"write to sftp done "; Q_ASSERT(wlen == rlen); tran_len += wlen ; //qDebug()<<" local read : "<< rlen << " sftp write :"<<wlen <<" up len :"<< tran_len ; // qDebug() <<" read len :"<< rlen <<" , write len: "<< wlen // << " tran len: "<< tran_len ; if (file_size == 0 ) { emit this->transfer_percent_changed(currFile, 100, tran_len, wlen); } else { pcnt = 100.0 *((double)tran_len / (double)file_size); // qDebug()<< QString("100.0 *((double)%1 / (double)%2)").arg(tran_len).arg(file_size)<<" = "<<pcnt ; emit this->transfer_percent_changed(currFile, pcnt, tran_len, wlen); } } q_file.close(); } // qDebug()<<"out cycle, close sftp..."; libssh2_sftp_close(sftp_handle); q_debug()<<"syncUpload done."; this->do_touch_sftp_file_with_time(remote_path, QFileInfo(local_path).lastModified()); emit this->syncFileStopped(currFile, 0); return 0; }