TQString TrashImpl::trashForMountPoint( const TQString& topdir, bool createIfNeeded ) const { // (1) Administrator-created $topdir/.Trash directory const TQString rootTrashDir = topdir + "/.Trash"; const TQCString rootTrashDir_c = TQFile::encodeName( rootTrashDir ); // Can't use TQFileInfo here since we need to test for the sticky bit uid_t uid = getuid(); KDE_struct_stat buff; const uint requiredBits = S_ISVTX; // Sticky bit required if ( KDE_lstat( rootTrashDir_c, &buff ) == 0 ) { if ( (S_ISDIR(buff.st_mode)) // must be a dir && (!S_ISLNK(buff.st_mode)) // not a symlink && ((buff.st_mode & requiredBits) == requiredBits) && (::access(rootTrashDir_c, W_OK)) ) { const TQString trashDir = rootTrashDir + "/" + TQString::number( uid ); const TQCString trashDir_c = TQFile::encodeName( trashDir ); if ( KDE_lstat( trashDir_c, &buff ) == 0 ) { if ( (buff.st_uid == uid) // must be owned by user && (S_ISDIR(buff.st_mode)) // must be a dir && (!S_ISLNK(buff.st_mode)) // not a symlink && (buff.st_mode & 0777) == 0700 ) { // rwx for user return trashDir; } kdDebug() << "Directory " << trashDir << " exists but didn't pass the security checks, can't use it" << endl; } else if ( createIfNeeded && initTrashDirectory( trashDir_c ) ) { return trashDir; } } else { kdDebug() << "Root trash dir " << rootTrashDir << " exists but didn't pass the security checks, can't use it" << endl; } } // (2) $topdir/.Trash-$uid const TQString trashDir = topdir + "/.Trash-" + TQString::number( uid ); const TQCString trashDir_c = TQFile::encodeName( trashDir ); if ( KDE_lstat( trashDir_c, &buff ) == 0 ) { if ( (buff.st_uid == uid) // must be owned by user && (S_ISDIR(buff.st_mode)) // must be a dir && (!S_ISLNK(buff.st_mode)) // not a symlink && ((buff.st_mode & 0777) == 0700) ) { // rwx for user, ------ for group and others if ( checkTrashSubdirs( trashDir_c ) ) return trashDir; } kdDebug() << "Directory " << trashDir << " exists but didn't pass the security checks, can't use it" << endl; // Exists, but not useable return TQString::null; } if ( createIfNeeded && initTrashDirectory( trashDir_c ) ) { return trashDir; } return TQString::null; }
void TrashProtocol::restore( const KUrl& trashURL ) { int trashId; QString fileId, relativePath; bool ok = TrashImpl::parseURL( trashURL, trashId, fileId, relativePath ); if ( !ok ) { error( KIO::ERR_SLAVE_DEFINED, i18n( "Malformed URL %1", trashURL.prettyUrl() ) ); return; } TrashedFileInfo info; ok = impl.infoForFile( trashId, fileId, info ); if ( !ok ) { error( impl.lastErrorCode(), impl.lastErrorMessage() ); return; } KUrl dest; dest.setPath( info.origPath ); if ( !relativePath.isEmpty() ) dest.addPath( relativePath ); // Check that the destination directory exists, to improve the error code in case it doesn't. const QString destDir = dest.directory(); KDE_struct_stat buff; if ( KDE_lstat( QFile::encodeName( destDir ), &buff ) == -1 ) { error( KIO::ERR_SLAVE_DEFINED, i18n( "The directory %1 does not exist anymore, so it is not possible to restore this item to its original location. " "You can either recreate that directory and use the restore operation again, or drag the item anywhere else to restore it.", destDir ) ); return; } copyOrMove( trashURL, dest, false /*overwrite*/, Move ); }
bool TrashImpl::initTrashDirectory( const TQCString& trashDir_c ) const { if ( ::mkdir( trashDir_c, 0700 ) != 0 ) return false; // This trash dir will be useable only if the directory is owned by user. // In theory this is the case, but not on e.g. USB keys... uid_t uid = getuid(); KDE_struct_stat buff; if ( KDE_lstat( trashDir_c, &buff ) != 0 ) return false; // huh? if ( (buff.st_uid == uid) // must be owned by user && ((buff.st_mode & 0777) == 0700) ) { // rwx for user, --- for group and others return checkTrashSubdirs( trashDir_c ); } else { kdDebug() << trashDir_c << " just created, by it doesn't have the right permissions, must be a FAT partition. Removing it again." << endl; // Not good, e.g. USB key. Delete again. // I'm paranoid, it would be better to find a solution that allows // to trash directly onto the USB key, but I don't see how that would // pass the security checks. It would also make the USB key appears as // empty when it's in fact full... ::rmdir( trashDir_c ); return false; } return true; }
int TrashImpl::findTrashDirectory( const TQString& origPath ) { kdDebug() << k_funcinfo << origPath << endl; // First check if same device as $HOME, then we use the home trash right away. KDE_struct_stat buff; if ( KDE_lstat( TQFile::encodeName( origPath ), &buff ) == 0 && buff.st_dev == m_homeDevice ) return 0; TQString mountPoint = TDEIO::findPathMountPoint( origPath ); const TQString trashDir = trashForMountPoint( mountPoint, true ); kdDebug() << "mountPoint=" << mountPoint << " trashDir=" << trashDir << endl; if ( trashDir.isEmpty() ) return 0; // no trash available on partition int id = idForTrashDirectory( trashDir ); if ( id > -1 ) { kdDebug() << " known with id " << id << endl; return id; } // new trash dir found, register it // but we need stability in the trash IDs, so that restoring or asking // for properties works even tdeio_trash gets killed because idle. #if 0 kdDebug() << k_funcinfo << "found " << trashDir << endl; m_trashDirectories.insert( ++m_lastId, trashDir ); if ( !mountPoint.endsWith( "/" ) ) mountPoint += '/'; m_topDirectories.insert( m_lastId, mountPoint ); return m_lastId; #endif scanTrashDirectories(); return idForTrashDirectory( trashDir ); }
void KStandardDirs::createSpecialResource(const char *type) { char hostname[256]; hostname[0] = 0; gethostname(hostname, 255); QString dir = QString("%1%2-%3").arg(localkdedir()).arg(type).arg(hostname); char link[1024]; link[1023] = 0; int result = readlink(QFile::encodeName(dir).data(), link, 1023); bool relink = (result == -1) && (errno == ENOENT); if(result > 0) { link[result] = 0; if(!QDir::isRelativePath(link)) { KDE_struct_stat stat_buf; int res = KDE_lstat(link, &stat_buf); if((res == -1) && (errno == ENOENT)) { relink = true; } else if((res == -1) || (!S_ISDIR(stat_buf.st_mode))) { fprintf(stderr, "Error: \"%s\" is not a directory.\n", link); relink = true; } else if(stat_buf.st_uid != getuid()) { fprintf(stderr, "Error: \"%s\" is owned by uid %d instead of uid %d.\n", link, stat_buf.st_uid, getuid()); relink = true; } } } if(relink) { QString srv = findExe(QString::fromLatin1("lnusertemp"), kfsstnd_defaultbindir()); if(srv.isEmpty()) srv = findExe(QString::fromLatin1("lnusertemp")); if(!srv.isEmpty()) { system(QFile::encodeName(srv) + " " + type); result = readlink(QFile::encodeName(dir).data(), link, 1023); } } if(result > 0) { link[result] = 0; if(link[0] == '/') dir = QFile::decodeName(link); else dir = QDir::cleanDirPath(dir + QFile::decodeName(link)); } addResourceDir(type, dir + '/'); }
static void createTestSymlink(const QString &path) { // Create symlink if it doesn't exist yet KDE_struct_stat buf; if(KDE_lstat(QFile::encodeName(path), &buf) != 0) { bool ok = symlink("/IDontExist", QFile::encodeName(path)) == 0; // broken symlink if(!ok) kdFatal() << "couldn't create symlink: " << strerror(errno) << endl; } }
static bool testLinkCountSupport(const QByteArray &fileName) { KDE_struct_stat st_buf; int result = -1; // Check if hardlinks raise the link count at all? if(!::link( fileName, QByteArray(fileName+".test") )) { result = KDE_lstat( fileName, &st_buf ); ::unlink( QByteArray(fileName+".test") ); } return (result < 0 || ((result == 0) && (st_buf.st_nlink == 2))); }
bool TrashProtocol::createUDSEntry(const QString &physicalPath, const QString &fileName, const QString &url, KIO::UDSEntry &entry, const TrashedFileInfo &info) { QCString physicalPath_c = QFile::encodeName(physicalPath); KDE_struct_stat buff; if(KDE_lstat(physicalPath_c, &buff) == -1) { kdWarning() << "couldn't stat " << physicalPath << endl; return false; } if(S_ISLNK(buff.st_mode)) { char buffer2[1000]; int n = readlink(physicalPath_c, buffer2, 1000); if(n != -1) { buffer2[n] = 0; } addAtom(entry, KIO::UDS_LINK_DEST, 0, QFile::decodeName(buffer2)); // Follow symlink // That makes sense in kio_file, but not in the trash, especially for the size // #136876 #if 0 if ( KDE_stat( physicalPath_c, &buff ) == -1 ) { // It is a link pointing to nowhere buff.st_mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO; buff.st_mtime = 0; buff.st_atime = 0; buff.st_size = 0; } #endif } mode_t type = buff.st_mode & S_IFMT; // extract file type mode_t access = buff.st_mode & 07777; // extract permissions access &= 07555; // make it readonly, since it's in the trashcan addAtom(entry, KIO::UDS_NAME, 0, fileName); addAtom(entry, KIO::UDS_FILE_TYPE, type); if(!url.isEmpty()) addAtom(entry, KIO::UDS_URL, 0, url); KMimeType::Ptr mt = KMimeType::findByPath(physicalPath, buff.st_mode); addAtom(entry, KIO::UDS_MIME_TYPE, 0, mt->name()); addAtom(entry, KIO::UDS_ACCESS, access); addAtom(entry, KIO::UDS_SIZE, buff.st_size); addAtom(entry, KIO::UDS_USER, 0, m_userName); // assumption addAtom(entry, KIO::UDS_GROUP, 0, m_groupName); // assumption addAtom(entry, KIO::UDS_MODIFICATION_TIME, buff.st_mtime); addAtom(entry, KIO::UDS_ACCESS_TIME, buff.st_atime); // ## or use it for deletion time? addAtom(entry, KIO::UDS_EXTRA, 0, info.origPath); addAtom(entry, KIO::UDS_EXTRA, 0, info.deletionDate.toString(Qt::ISODate)); return true; }
bool TrashProtocol::createUDSEntry( const QString& physicalPath, const QString& displayFileName, const QString& internalFileName, KIO::UDSEntry& entry, const TrashedFileInfo& info ) { QByteArray physicalPath_c = QFile::encodeName( physicalPath ); KDE_struct_stat buff; if ( KDE_lstat( physicalPath_c, &buff ) == -1 ) { kWarning() << "couldn't stat " << physicalPath ; return false; } if (S_ISLNK(buff.st_mode)) { char buffer2[ 1000 ]; int n = readlink( physicalPath_c, buffer2, 999 ); if ( n != -1 ) { buffer2[ n ] = 0; } entry.insert( KIO::UDSEntry::UDS_LINK_DEST, QFile::decodeName( buffer2 ) ); // Follow symlink // That makes sense in kio_file, but not in the trash, especially for the size // #136876 #if 0 if ( KDE_stat( physicalPath_c, &buff ) == -1 ) { // It is a link pointing to nowhere buff.st_mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO; buff.st_mtime = 0; buff.st_atime = 0; buff.st_size = 0; } #endif } mode_t type = buff.st_mode & S_IFMT; // extract file type mode_t access = buff.st_mode & 07777; // extract permissions access &= 07555; // make it readonly, since it's in the trashcan Q_ASSERT(!internalFileName.isEmpty()); entry.insert( KIO::UDSEntry::UDS_NAME, internalFileName ); // internal filename, like "0-foo" entry.insert( KIO::UDSEntry::UDS_DISPLAY_NAME, displayFileName ); // user-visible filename, like "foo" entry.insert( KIO::UDSEntry::UDS_FILE_TYPE, type ); //if ( !url.isEmpty() ) // entry.insert( KIO::UDSEntry::UDS_URL, url ); KMimeType::Ptr mt = KMimeType::findByPath( physicalPath, buff.st_mode ); if ( mt ) entry.insert( KIO::UDSEntry::UDS_MIME_TYPE, mt->name() ); entry.insert( KIO::UDSEntry::UDS_ACCESS, access ); entry.insert( KIO::UDSEntry::UDS_SIZE, buff.st_size ); entry.insert( KIO::UDSEntry::UDS_USER, m_userName ); // assumption entry.insert( KIO::UDSEntry::UDS_GROUP, m_groupName ); // assumption entry.insert( KIO::UDSEntry::UDS_MODIFICATION_TIME, buff.st_mtime ); entry.insert( KIO::UDSEntry::UDS_ACCESS_TIME, buff.st_atime ); // ## or use it for deletion time? entry.insert( KIO::UDSEntry::UDS_EXTRA, info.origPath ); entry.insert( KIO::UDSEntry::UDS_EXTRA + 1, info.deletionDate.toString( Qt::ISODate ) ); return true; }
static void moveLocalSymlink(const QString &src, const QString &dest) { KDE_struct_stat buf; assert(KDE_lstat(QFile::encodeName(src), &buf) == 0); KURL u; u.setPath(src); KURL d; d.setPath(dest); // move the symlink with move, NOT with file_move bool ok = KIO::NetAccess::move(u, d); if(!ok) kdWarning() << KIO::NetAccess::lastError() << endl; assert(ok); assert(KDE_lstat(QFile::encodeName(dest), &buf) == 0); assert(!QFile::exists(src)); // not there anymore // move it back with KIO::move() ok = KIO::NetAccess::move(d, u, 0); assert(ok); assert(KDE_lstat(QFile::encodeName(dest), &buf) != 0); // doesn't exist anymore assert(KDE_lstat(QFile::encodeName(src), &buf) == 0); // it's back }
QString KFileItem::user() const { if ( m_user.isEmpty() && m_bIsLocalURL ) { KDE_struct_stat buff; if ( KDE_lstat( QFile::encodeName(m_url.path( -1 )), &buff ) == 0) // get uid/gid of the link, if it's a link { struct passwd *user = getpwuid( buff.st_uid ); if ( user != 0L ) m_user = QString::fromLocal8Bit(user->pw_name); } } return m_user; }
TrashImpl::TrashImpl() : TQObject(), m_lastErrorCode( 0 ), m_initStatus( InitToBeDone ), m_lastId( 0 ), m_homeDevice( 0 ), m_trashDirectoriesScanned( false ), m_mibEnum( TDEGlobal::locale()->fileEncodingMib() ), // not using tdeio_trashrc since TDEIO uses that one already for tdeio_trash // so better have a separate one, for faster parsing by e.g. kmimetype.cpp m_config( "trashrc" ) { KDE_struct_stat buff; if ( KDE_lstat( TQFile::encodeName( TQDir::homeDirPath() ), &buff ) == 0 ) { m_homeDevice = buff.st_dev; } else { kdError() << "Should never happen: couldn't stat $HOME " << strerror( errno ) << endl; } }
QString KFileItem::group() const { #ifdef Q_OS_UNIX if (m_group.isEmpty() && m_bIsLocalURL ) { KDE_struct_stat buff; if ( KDE_lstat( QFile::encodeName(m_url.path( -1 )), &buff ) == 0) // get uid/gid of the link, if it's a link { struct group *ge = getgrgid( buff.st_gid ); if ( ge != 0L ) { m_group = QString::fromLocal8Bit(ge->gr_name); if (m_group.isEmpty()) m_group.sprintf("%d",ge->gr_gid); } else m_group.sprintf("%d",buff.st_gid); } } #endif return m_group; }
bool KStandardDirs::makeDir(const QString &dir, int mode) { // we want an absolute path if(QDir::isRelativePath(dir)) return false; QString target = dir; uint len = target.length(); // append trailing slash if missing if(dir.at(len - 1) != '/') target += '/'; QString base(""); uint i = 1; while(i < len) { KDE_struct_stat st; int pos = target.find('/', i); base += target.mid(i - 1, pos - i + 1); QCString baseEncoded = QFile::encodeName(base); // bail out if we encountered a problem if(KDE_stat(baseEncoded, &st) != 0) { // Directory does not exist.... // Or maybe a dangling symlink ? if(KDE_lstat(baseEncoded, &st) == 0) (void)unlink(baseEncoded); // try removing if(KDE_mkdir(baseEncoded, (mode_t)mode) != 0) { baseEncoded.prepend("trying to create local folder "); perror(baseEncoded.data()); return false; // Couldn't create it :-( } } i = pos + 1; } return true; }
bool TrashImpl::del( int trashId, const TQString& fileId ) { TQString info = infoPath(trashId, fileId); TQString file = filesPath(trashId, fileId); TQCString info_c = TQFile::encodeName(info); KDE_struct_stat buff; if ( KDE_lstat( info_c.data(), &buff ) == -1 ) { if ( errno == EACCES ) error( TDEIO::ERR_ACCESS_DENIED, file ); else error( TDEIO::ERR_DOES_NOT_EXIST, file ); return false; } if ( !synchronousDel( file, true, TQFileInfo(file).isDir() ) ) return false; TQFile::remove( info ); fileRemoved(); return true; }
bool KArchive::addLocalFile(const QString &fileName, const QString &destName) { QFileInfo fileInfo(fileName); if(!fileInfo.isFile() && !fileInfo.isSymLink()) { kdWarning() << "KArchive::addLocalFile " << fileName << " doesn't exist or is not a regular file." << endl; return false; } KDE_struct_stat fi; if(KDE_lstat(QFile::encodeName(fileName), &fi) == -1) { kdWarning() << "KArchive::addLocalFile stating " << fileName << " failed: " << strerror(errno) << endl; return false; } if(fileInfo.isSymLink()) { return writeSymLink(destName, fileInfo.readLink(), fileInfo.owner(), fileInfo.group(), fi.st_mode, fi.st_atime, fi.st_mtime, fi.st_ctime); } /*end if*/ uint size = fileInfo.size(); // the file must be opened before prepareWriting is called, otherwise // if the opening fails, no content will follow the already written // header and the tar file is effectively f*cked up QFile file(fileName); if(!file.open(IO_ReadOnly)) { kdWarning() << "KArchive::addLocalFile couldn't open file " << fileName << endl; return false; } if(!prepareWriting(destName, fileInfo.owner(), fileInfo.group(), size, fi.st_mode, fi.st_atime, fi.st_mtime, fi.st_ctime)) { kdWarning() << "KArchive::addLocalFile prepareWriting " << destName << " failed" << endl; return false; } // Read and write data in chunks to minimize memory usage QByteArray array(8 * 1024); int n; uint total = 0; while((n = file.readBlock(array.data(), array.size())) > 0) { if(!writeData(array.data(), n)) { kdWarning() << "KArchive::addLocalFile writeData failed" << endl; return false; } total += n; } Q_ASSERT(total == size); if(!doneWriting(size)) { kdWarning() << "KArchive::addLocalFile doneWriting failed" << endl; return false; } return true; }
static time_t getTimeStamp(const QString &item) { KDE_struct_stat info; return !item.isEmpty() && 0==KDE_lstat(QFile::encodeName(item), &info) ? info.st_mtime : 0; }
static KLockFile::LockResult lockFile(const QString &lockFile, KDE_struct_stat &st_buf, bool &linkCountSupport, const KComponentData &componentData) { QByteArray lockFileName = QFile::encodeName( lockFile ); int result = KDE_lstat( lockFileName, &st_buf ); if (result == 0) return KLockFile::LockFail; KTemporaryFile uniqueFile(componentData); uniqueFile.setFileTemplate(lockFile); if (!uniqueFile.open()) return KLockFile::LockError; uniqueFile.setPermissions(QFile::ReadUser|QFile::WriteUser|QFile::ReadGroup|QFile::ReadOther); char hostname[256]; hostname[0] = 0; gethostname(hostname, 255); hostname[255] = 0; QString componentName = componentData.componentName(); QTextStream stream(&uniqueFile); stream << QString::number(getpid()) << endl << componentName << endl << hostname << endl; stream.flush(); QByteArray uniqueName = QFile::encodeName( uniqueFile.fileName() ); // Create lock file result = ::link( uniqueName, lockFileName ); if (result != 0) return KLockFile::LockError; if (!linkCountSupport) return KLockFile::LockOK; KDE_struct_stat st_buf2; result = KDE_lstat( uniqueName, &st_buf2 ); if (result != 0) return KLockFile::LockError; result = KDE_lstat( lockFileName, &st_buf ); if (result != 0) return KLockFile::LockError; if (st_buf != st_buf2 || S_ISLNK(st_buf.st_mode) || S_ISLNK(st_buf2.st_mode)) { // SMBFS supports hardlinks by copying the file, as a result the above test will always fail // cifs increases link count artifically but the inodes are still different if ((st_buf2.st_nlink > 1 || ((st_buf.st_nlink == 1) && (st_buf2.st_nlink == 1))) && (st_buf.st_ino != st_buf2.st_ino)) { linkCountSupport = testLinkCountSupport(uniqueName); if (!linkCountSupport) return KLockFile::LockOK; // Link count support is missing... assume everything is OK. } return KLockFile::LockFail; } return KLockFile::LockOK; }
static KLockFile::LockResult deleteStaleLock(const QString &lockFile, KDE_struct_stat &st_buf, bool &linkCountSupport, const KComponentData &componentData) { // This is dangerous, we could be deleting a new lock instead of // the old stale one, let's be very careful // Create temp file KTemporaryFile *ktmpFile = new KTemporaryFile(componentData); ktmpFile->setFileTemplate(lockFile); if (!ktmpFile->open()) return KLockFile::LockError; QByteArray lckFile = QFile::encodeName(lockFile); QByteArray tmpFile = QFile::encodeName(ktmpFile->fileName()); delete ktmpFile; // link to lock file if (::link(lckFile, tmpFile) != 0) return KLockFile::LockFail; // Try again later // check if link count increased with exactly one // and if the lock file still matches KDE_struct_stat st_buf1; KDE_struct_stat st_buf2; memcpy(&st_buf1, &st_buf, sizeof(KDE_struct_stat)); st_buf1.st_nlink++; if ((KDE_lstat(tmpFile, &st_buf2) == 0) && st_buf1 == st_buf2) { if ((KDE_lstat(lckFile, &st_buf2) == 0) && st_buf1 == st_buf2) { // - - if yes, delete lock file, delete temp file, retry lock qWarning("WARNING: deleting stale lockfile %s", lckFile.data()); ::unlink(lckFile); ::unlink(tmpFile); return KLockFile::LockOK; } } // SMBFS supports hardlinks by copying the file, as a result the above test will always fail if (linkCountSupport) { linkCountSupport = testLinkCountSupport(tmpFile); } if (!linkCountSupport) { // Without support for link counts we will have a little race condition qWarning("WARNING: deleting stale lockfile %s", lckFile.data()); ::unlink(tmpFile); if (::unlink(lckFile) < 0) { qWarning("WARNING: Problem deleting stale lockfile %s: %s", lckFile.data(), strerror(errno)); return KLockFile::LockFail; } return KLockFile::LockOK; } // Failed to delete stale lock file qWarning("WARNING: Problem deleting stale lockfile %s", lckFile.data()); ::unlink(tmpFile); return KLockFile::LockFail; }
void KFileItem::init( bool _determineMimeTypeOnDemand ) { m_access = QString::null; m_size = (KIO::filesize_t) -1; // metaInfo = KFileMetaInfo(); for ( int i = 0; i < NumFlags; i++ ) m_time[i] = (time_t) -1; // determine mode and/or permissions if unknown if ( m_fileMode == KFileItem::Unknown || m_permissions == KFileItem::Unknown ) { mode_t mode = 0; if ( m_url.isLocalFile() ) { /* directories may not have a slash at the end if * we want to stat() them; it requires that we * change into it .. which may not be allowed * stat("/is/unaccessible") -> rwx------ * stat("/is/unaccessible/") -> EPERM H.Z. * This is the reason for the -1 */ KDE_struct_stat buf; QCString path = QFile::encodeName(m_url.path( -1 )); if ( KDE_lstat( path.data(), &buf ) == 0 ) { mode = buf.st_mode; if ( S_ISLNK( mode ) ) { m_bLink = true; if ( KDE_stat( path.data(), &buf ) == 0 ) mode = buf.st_mode; else // link pointing to nowhere (see kio/file/file.cc) mode = (S_IFMT-1) | S_IRWXU | S_IRWXG | S_IRWXO; } // While we're at it, store the times m_time[ Modification ] = buf.st_mtime; m_time[ Access ] = buf.st_atime; if ( m_fileMode == KFileItem::Unknown ) m_fileMode = mode & S_IFMT; // extract file type if ( m_permissions == KFileItem::Unknown ) m_permissions = mode & 07777; // extract permissions } } } // determine the mimetype if (!m_pMimeType && !m_url.isEmpty()) { bool accurate = false; bool isLocalURL; KURL url = mostLocalURL(isLocalURL); m_pMimeType = KMimeType::findByURL( url, m_fileMode, isLocalURL, // use fast mode if not mimetype on demand _determineMimeTypeOnDemand, &accurate ); //kdDebug() << "finding mimetype for " << url.url() << " : " << m_pMimeType->name() << endl; // if we didn't use fast mode, or if we got a result, then this is the mimetype // otherwise, determineMimeType will be able to do better. m_bMimeTypeKnown = (!_determineMimeTypeOnDemand) || accurate; } }
int KDEsuClient::connect() { if(sockfd >= 0) close(sockfd); if(access(sock, R_OK | W_OK)) { sockfd = -1; return -1; } sockfd = socket(PF_UNIX, SOCK_STREAM, 0); if(sockfd < 0) { kdWarning(900) << k_lineinfo << "socket(): " << perror << "\n"; return -1; } struct sockaddr_un addr; addr.sun_family = AF_UNIX; strcpy(addr.sun_path, sock); if(::connect(sockfd, (struct sockaddr *)&addr, SUN_LEN(&addr)) < 0) { kdWarning(900) << k_lineinfo << "connect():" << perror << endl; close(sockfd); sockfd = -1; return -1; } #if !defined(SO_PEERCRED) || !defined(HAVE_STRUCT_UCRED) #if defined(HAVE_GETPEEREID) uid_t euid; gid_t egid; // Security: if socket exists, we must own it if(getpeereid(sockfd, &euid, &egid) == 0) { if(euid != getuid()) { kdWarning(900) << "socket not owned by me! socket uid = " << euid << endl; close(sockfd); sockfd = -1; return -1; } } #else #ifdef __GNUC__ #warning "Using sloppy security checks" #endif // We check the owner of the socket after we have connected. // If the socket was somehow not ours an attacker will be able // to delete it after we connect but shouldn't be able to // create a socket that is owned by us. KDE_struct_stat s; if(KDE_lstat(sock, &s) != 0) { kdWarning(900) << "stat failed (" << sock << ")" << endl; close(sockfd); sockfd = -1; return -1; } if(s.st_uid != getuid()) { kdWarning(900) << "socket not owned by me! socket uid = " << s.st_uid << endl; close(sockfd); sockfd = -1; return -1; } if(!S_ISSOCK(s.st_mode)) { kdWarning(900) << "socket is not a socket (" << sock << ")" << endl; close(sockfd); sockfd = -1; return -1; } #endif #else struct ucred cred; socklen_t siz = sizeof(cred); // Security: if socket exists, we must own it if(getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cred, &siz) == 0) { if(cred.uid != getuid()) { kdWarning(900) << "socket not owned by me! socket uid = " << cred.uid << endl; close(sockfd); sockfd = -1; return -1; } } #endif return 0; }
bool TrashImpl::createInfo( const TQString& origPath, int& trashId, TQString& fileId ) { kdDebug() << k_funcinfo << origPath << endl; // Check source const TQCString origPath_c( TQFile::encodeName( origPath ) ); KDE_struct_stat buff_src; if ( KDE_lstat( origPath_c.data(), &buff_src ) == -1 ) { if ( errno == EACCES ) error( TDEIO::ERR_ACCESS_DENIED, origPath ); else error( TDEIO::ERR_DOES_NOT_EXIST, origPath ); return false; } // Choose destination trash trashId = findTrashDirectory( origPath ); if ( trashId < 0 ) { kdWarning() << "OUCH - internal error, TrashImpl::findTrashDirectory returned " << trashId << endl; return false; // ### error() needed? } kdDebug() << k_funcinfo << "trashing to " << trashId << endl; // Grab original filename KURL url; url.setPath( origPath ); const TQString origFileName = url.fileName(); // Make destination file in info/ url.setPath( infoPath( trashId, origFileName ) ); // we first try with origFileName KURL baseDirectory; baseDirectory.setPath( url.directory() ); // Here we need to use O_EXCL to avoid race conditions with other tdeioslave processes int fd = 0; do { kdDebug() << k_funcinfo << "trying to create " << url.path() << endl; fd = ::open( TQFile::encodeName( url.path() ), O_WRONLY | O_CREAT | O_EXCL, 0600 ); if ( fd < 0 ) { if ( errno == EEXIST ) { url.setFileName( TDEIO::RenameDlg::suggestName( baseDirectory, url.fileName() ) ); // and try again on the next iteration } else { error( TDEIO::ERR_COULD_NOT_WRITE, url.path() ); return false; } } } while ( fd < 0 ); const TQString infoPath = url.path(); fileId = url.fileName(); Q_ASSERT( fileId.endsWith( ".trashinfo" ) ); fileId.truncate( fileId.length() - 10 ); // remove .trashinfo from fileId FILE* file = ::fdopen( fd, "w" ); if ( !file ) { // can't see how this would happen error( TDEIO::ERR_COULD_NOT_WRITE, infoPath ); return false; } // Contents of the info file. We could use KSimpleConfig, but that would // mean closing and reopening fd, i.e. opening a race condition... TQCString info = "[Trash Info]\n"; info += "Path="; // Escape filenames according to the way they are encoded on the filesystem // All this to basically get back to the raw 8-bit representation of the filename... if ( trashId == 0 ) // home trash: absolute path info += KURL::encode_string( origPath, m_mibEnum ).latin1(); else info += KURL::encode_string( makeRelativePath( topDirectoryPath( trashId ), origPath ), m_mibEnum ).latin1(); info += "\n"; info += "DeletionDate="; info += TQDateTime::currentDateTime().toString( Qt::ISODate ).latin1(); info += "\n"; size_t sz = info.size() - 1; // avoid trailing 0 from QCString size_t written = ::fwrite(info.data(), 1, sz, file); if ( written != sz ) { ::fclose( file ); TQFile::remove( infoPath ); error( TDEIO::ERR_DISK_FULL, infoPath ); return false; } ::fclose( file ); kdDebug() << k_funcinfo << "info file created in trashId=" << trashId << " : " << fileId << endl; return true; }