Changeset View
Changeset View
Standalone View
Standalone View
src/ioslaves/file/file.cpp
Show First 20 Lines • Show All 846 Lines • ▼ Show 20 Line(s) | 842 | if (it == mGroupcache.end()) { | |||
---|---|---|---|---|---|
847 | } | 847 | } | ||
848 | it = mGroupcache.insert(gid, name); | 848 | it = mGroupcache.insert(gid, name); | ||
849 | } | 849 | } | ||
850 | return *it; | 850 | return *it; | ||
851 | } | 851 | } | ||
852 | 852 | | |||
853 | #if HAVE_STATX | 853 | #if HAVE_STATX | ||
854 | // statx syscall is available | 854 | // statx syscall is available | ||
855 | inline int LSTAT(const char* path, struct statx * buff) { | 855 | inline int LSTAT(const char* path, struct statx * buff, KIO::StatDetails details) { | ||
856 | return statx(AT_FDCWD, path, AT_SYMLINK_NOFOLLOW, STATX_BASIC_STATS | STATX_BTIME, buff); | 856 | uint32_t mask = 0; | ||
857 | if (details & KIO::Basic) { | ||||
858 | // filename, access, type, size, linkdest | ||||
859 | mask |= STATX_SIZE | STATX_TYPE; | ||||
860 | } | ||||
861 | if (details & KIO::User) { | ||||
862 | // uid, gid | ||||
863 | mask |= STATX_UID | STATX_GID; | ||||
857 | } | 864 | } | ||
858 | inline int STAT(const char* path, struct statx * buff) { | 865 | if (details & KIO::Time) { | ||
866 | // atime, mtime, btime | ||||
867 | mask |= STATX_ATIME | STATX_MTIME | STATX_BTIME; | ||||
868 | } | ||||
869 | if (details & KIO::Inode) { | ||||
870 | // dev, inode | ||||
871 | mask |= STATX_INO; | ||||
872 | } | ||||
873 | return statx(AT_FDCWD, path, AT_SYMLINK_NOFOLLOW, mask, buff); | ||||
874 | } | ||||
875 | inline int STAT(const char* path, struct statx * buff, KIO::StatDetails details) { | ||||
876 | Q_UNUSED(details) | ||||
859 | return statx(AT_FDCWD, path, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS | STATX_BTIME, buff); | 877 | return statx(AT_FDCWD, path, AT_STATX_SYNC_AS_STAT, STATX_BASIC_STATS | STATX_BTIME, buff); | ||
860 | } | 878 | } | ||
861 | inline static uint16_t stat_mode(struct statx &buf) { return buf.stx_mode; } | 879 | inline static uint16_t stat_mode(struct statx &buf) { return buf.stx_mode; } | ||
862 | inline static uint32_t stat_dev(struct statx &buf) { return buf.stx_dev_major; } | 880 | inline static uint32_t stat_dev(struct statx &buf) { return buf.stx_dev_major; } | ||
863 | inline static uint64_t stat_ino(struct statx &buf) { return buf.stx_ino; } | 881 | inline static uint64_t stat_ino(struct statx &buf) { return buf.stx_ino; } | ||
864 | inline static uint64_t stat_size(struct statx &buf) { return buf.stx_size; } | 882 | inline static uint64_t stat_size(struct statx &buf) { return buf.stx_size; } | ||
865 | inline static uint32_t stat_uid(struct statx &buf) { return buf.stx_uid; } | 883 | inline static uint32_t stat_uid(struct statx &buf) { return buf.stx_uid; } | ||
866 | inline static uint32_t stat_gid(struct statx &buf) { return buf.stx_gid; } | 884 | inline static uint32_t stat_gid(struct statx &buf) { return buf.stx_gid; } | ||
867 | inline static int64_t stat_atime(struct statx &buf) { return buf.stx_atime.tv_sec; } | 885 | inline static int64_t stat_atime(struct statx &buf) { return buf.stx_atime.tv_sec; } | ||
868 | inline static int64_t stat_mtime(struct statx &buf) { return buf.stx_mtime.tv_sec; } | 886 | inline static int64_t stat_mtime(struct statx &buf) { return buf.stx_mtime.tv_sec; } | ||
869 | #else | 887 | #else | ||
870 | // regular stat struct | 888 | // regular stat struct | ||
871 | inline int LSTAT(const char* path, QT_STATBUF * buff) { | 889 | inline int LSTAT(const char* path, QT_STATBUF * buff, KIO::StatDetails details) { | ||
890 | Q_UNUSED(details) | ||||
872 | return QT_LSTAT(path, buff); | 891 | return QT_LSTAT(path, buff); | ||
873 | } | 892 | } | ||
874 | inline int STAT(const char* path, QT_STATBUF * buff) { | 893 | inline int STAT(const char* path, QT_STATBUF * buff, KIO::StatDetails details) { | ||
894 | Q_UNUSED(details) | ||||
875 | return QT_STAT(path, buff); | 895 | return QT_STAT(path, buff); | ||
876 | } | 896 | } | ||
877 | inline static mode_t stat_mode(QT_STATBUF &buf) { return buf.st_mode; } | 897 | inline static mode_t stat_mode(QT_STATBUF &buf) { return buf.st_mode; } | ||
878 | inline static dev_t stat_dev(QT_STATBUF &buf) { return buf.st_dev; } | 898 | inline static dev_t stat_dev(QT_STATBUF &buf) { return buf.st_dev; } | ||
879 | inline static ino_t stat_ino(QT_STATBUF &buf) { return buf.st_ino; } | 899 | inline static ino_t stat_ino(QT_STATBUF &buf) { return buf.st_ino; } | ||
880 | inline static off_t stat_size(QT_STATBUF &buf) { return buf.st_size; } | 900 | inline static off_t stat_size(QT_STATBUF &buf) { return buf.st_size; } | ||
881 | #ifndef Q_OS_WIN | 901 | #ifndef Q_OS_WIN | ||
882 | inline static uid_t stat_uid(QT_STATBUF &buf) { return buf.st_uid; } | 902 | inline static uid_t stat_uid(QT_STATBUF &buf) { return buf.st_uid; } | ||
883 | inline static gid_t stat_gid(QT_STATBUF &buf) { return buf.st_gid; } | 903 | inline static gid_t stat_gid(QT_STATBUF &buf) { return buf.st_gid; } | ||
884 | #endif | 904 | #endif | ||
885 | inline static time_t stat_atime(QT_STATBUF &buf) { return buf.st_atime; } | 905 | inline static time_t stat_atime(QT_STATBUF &buf) { return buf.st_atime; } | ||
886 | inline static time_t stat_mtime(QT_STATBUF &buf) { return buf.st_mtime; } | 906 | inline static time_t stat_mtime(QT_STATBUF &buf) { return buf.st_mtime; } | ||
887 | #endif | 907 | #endif | ||
888 | 908 | | |||
889 | bool FileProtocol::createUDSEntry(const QString &filename, const QByteArray &path, UDSEntry &entry, | 909 | bool FileProtocol::createUDSEntry(const QString &filename, const QByteArray &path, UDSEntry &entry, | ||
890 | short int details) | 910 | KIO::StatDetails details) | ||
891 | { | 911 | { | ||
892 | assert(entry.count() == 0); // by contract :-) | 912 | assert(entry.count() == 0); // by contract :-) | ||
893 | switch (details) { | 913 | int entries = 0; | ||
894 | case 0: | 914 | if (details & KIO::Basic) { | ||
dfaure: int is actually faster on most CPUs, and reserve() will convert it to an int anyway, so it… | |||||
Did you know you can just write if (details & KIO::StatJob::Basic)? Or did you use testFlag() for a specific reason? dfaure: Did you know you can just write `if (details & KIO::StatJob::Basic)`?
This is more C++-like… | |||||
I used testFlag because i was documented, and I still have to familiar myself with C/C++. meven: I used testFlag because i was documented, and I still have to familiar myself with C/C++. | |||||
895 | // filename, access, type, size, linkdest | 915 | // filename, access, type, size, linkdest | ||
896 | entry.reserve(5); | 916 | entries += 5; | ||
897 | break; | 917 | } | ||
898 | case 1: | 918 | if (details & KIO::User) { | ||
899 | // uid, gid, atime, mtime, btime | 919 | // uid, gid | ||
900 | entry.reserve(10); | 920 | entries += 2; | ||
901 | break; | 921 | } | ||
902 | case 2: | 922 | if (details & KIO::Time) { | ||
923 | // atime, mtime, btime | ||||
924 | entries += 3; | ||||
925 | } | ||||
926 | if (details & KIO::Acl) { | ||||
903 | // acl data | 927 | // acl data | ||
904 | entry.reserve(13); | 928 | entries += 3; | ||
905 | break; | 929 | } | ||
906 | default: // case details > 2 | 930 | if (details & KIO::Inode) { | ||
907 | // dev, inode | 931 | // dev, inode | ||
908 | entry.reserve(15); | 932 | entries += 2; | ||
909 | break; | | |||
910 | } | 933 | } | ||
934 | entry.reserve(entries); | ||||
935 | | ||||
936 | if (details & KIO::Basic) { | ||||
911 | entry.fastInsert(KIO::UDSEntry::UDS_NAME, filename); | 937 | entry.fastInsert(KIO::UDSEntry::UDS_NAME, filename); | ||
938 | } | ||||
912 | 939 | | |||
913 | mode_t type; | 940 | mode_t type; | ||
914 | mode_t access; | 941 | mode_t access; | ||
915 | bool isBrokenSymLink = false; | 942 | bool isBrokenSymLink = false; | ||
916 | signed long long size = 0LL; | 943 | signed long long size = 0LL; | ||
917 | #if HAVE_POSIX_ACL | 944 | #if HAVE_POSIX_ACL | ||
918 | QByteArray targetPath = path; | 945 | QByteArray targetPath = path; | ||
919 | #endif | 946 | #endif | ||
920 | 947 | | |||
921 | #if HAVE_STATX | 948 | #if HAVE_STATX | ||
922 | // statx syscall is available | 949 | // statx syscall is available | ||
923 | struct statx buff; | 950 | struct statx buff; | ||
924 | #else | 951 | #else | ||
925 | QT_STATBUF buff; | 952 | QT_STATBUF buff; | ||
926 | #endif | 953 | #endif | ||
927 | 954 | | |||
928 | if (LSTAT(path.data(), &buff) == 0) { | 955 | if (LSTAT(path.data(), &buff, details) == 0) { | ||
929 | 956 | | |||
930 | if (details > 2) { | 957 | if (details & KIO::Inode) { | ||
931 | entry.fastInsert(KIO::UDSEntry::UDS_DEVICE_ID, stat_dev(buff)); | 958 | entry.fastInsert(KIO::UDSEntry::UDS_DEVICE_ID, stat_dev(buff)); | ||
932 | entry.fastInsert(KIO::UDSEntry::UDS_INODE, stat_ino(buff)); | 959 | entry.fastInsert(KIO::UDSEntry::UDS_INODE, stat_ino(buff)); | ||
933 | } | 960 | } | ||
934 | 961 | | |||
935 | if ((stat_mode(buff) & QT_STAT_MASK) == QT_STAT_LNK) { | 962 | if ((stat_mode(buff) & QT_STAT_MASK) == QT_STAT_LNK) { | ||
936 | 963 | | |||
964 | if (details & KIO::Basic) { | ||||
937 | #ifdef Q_OS_WIN | 965 | #ifdef Q_OS_WIN | ||
938 | const QString linkTarget = QFile::symLinkTarget(QFile::decodeName(path)); | 966 | const QString linkTarget = QFile::symLinkTarget(QFile::decodeName(path)); | ||
939 | #else | 967 | #else | ||
940 | // Use readlink on Unix because symLinkTarget turns relative targets into absolute (#352927) | 968 | // Use readlink on Unix because symLinkTarget turns relative targets into absolute (#352927) | ||
941 | #if HAVE_STATX | 969 | #if HAVE_STATX | ||
942 | size_t lowerBound = 256; | 970 | size_t lowerBound = 256; | ||
943 | size_t higherBound = 1024; | 971 | size_t higherBound = 1024; | ||
944 | uint64_t s = stat_size(buff); | 972 | uint64_t s = stat_size(buff); | ||
Show All 24 Lines | 993 | } else if (n > 0 && static_cast<SizeType>(n) != bufferSize) { | |||
969 | break; | 997 | break; | ||
970 | } | 998 | } | ||
971 | bufferSize *= 2; | 999 | bufferSize *= 2; | ||
972 | linkTargetBuffer.resize(bufferSize); | 1000 | linkTargetBuffer.resize(bufferSize); | ||
973 | } | 1001 | } | ||
974 | const QString linkTarget = QFile::decodeName(linkTargetBuffer); | 1002 | const QString linkTarget = QFile::decodeName(linkTargetBuffer); | ||
975 | #endif | 1003 | #endif | ||
976 | entry.fastInsert(KIO::UDSEntry::UDS_LINK_DEST, linkTarget); | 1004 | entry.fastInsert(KIO::UDSEntry::UDS_LINK_DEST, linkTarget); | ||
1005 | } | ||||
977 | 1006 | | |||
978 | // A symlink -> follow it only if details>1 | 1007 | // A symlink | ||
979 | if (details > 1) { | 1008 | if (details & KIO::ResolveSymlink) { | ||
980 | if (STAT(path.constData(), &buff) == -1) { | 1009 | if (STAT(path.constData(), &buff, details) == -1) { | ||
981 | isBrokenSymLink = true; | 1010 | isBrokenSymLink = true; | ||
982 | } else { | 1011 | } else { | ||
983 | #if HAVE_POSIX_ACL | 1012 | #if HAVE_POSIX_ACL | ||
1013 | if (details & KIO::Acl) { | ||||
984 | // valid symlink, will get the ACLs of the destination | 1014 | // valid symlink, will get the ACLs of the destination | ||
985 | targetPath = linkTargetBuffer; | 1015 | targetPath = linkTargetBuffer; | ||
1016 | } | ||||
986 | #endif | 1017 | #endif | ||
987 | } | 1018 | } | ||
988 | } | 1019 | } | ||
989 | } | 1020 | } | ||
990 | } else { | 1021 | } else { | ||
991 | // qCWarning(KIO_FILE) << "lstat didn't work on " << path.data(); | 1022 | // qCWarning(KIO_FILE) << "lstat didn't work on " << path.data(); | ||
992 | return false; | 1023 | return false; | ||
993 | } | 1024 | } | ||
994 | 1025 | | |||
1026 | if (details & KIO::Basic) { | ||||
995 | if (isBrokenSymLink) { | 1027 | if (isBrokenSymLink) { | ||
996 | // It is a link pointing to nowhere | 1028 | // It is a link pointing to nowhere | ||
997 | type = S_IFMT - 1; | 1029 | type = S_IFMT - 1; | ||
998 | access = S_IRWXU | S_IRWXG | S_IRWXO; | 1030 | access = S_IRWXU | S_IRWXG | S_IRWXO; | ||
999 | size = 0LL; | 1031 | size = 0LL; | ||
1000 | } else { | 1032 | } else { | ||
1001 | type = stat_mode(buff) & S_IFMT; // extract file type | 1033 | type = stat_mode(buff) & S_IFMT; // extract file type | ||
1002 | access = stat_mode(buff) & 07777; // extract permissions | 1034 | access = stat_mode(buff) & 07777; // extract permissions | ||
1003 | size = stat_size(buff); | 1035 | size = stat_size(buff); | ||
1004 | } | 1036 | } | ||
1005 | 1037 | | |||
1006 | entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, type); | 1038 | entry.fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, type); | ||
1007 | entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, access); | 1039 | entry.fastInsert(KIO::UDSEntry::UDS_ACCESS, access); | ||
1008 | entry.fastInsert(KIO::UDSEntry::UDS_SIZE, size); | 1040 | entry.fastInsert(KIO::UDSEntry::UDS_SIZE, size); | ||
1041 | } | ||||
1009 | 1042 | | |||
1010 | #if HAVE_POSIX_ACL | 1043 | #if HAVE_POSIX_ACL | ||
1011 | if (details > 1) { | 1044 | if (details & KIO::Acl) { | ||
1012 | /* Append an atom indicating whether the file has extended acl information | 1045 | /* Append an atom indicating whether the file has extended acl information | ||
1013 | * and if withACL is specified also one with the acl itself. If it's a directory | 1046 | * and if withACL is specified also one with the acl itself. If it's a directory | ||
1014 | * and it has a default ACL, also append that. */ | 1047 | * and it has a default ACL, also append that. */ | ||
1015 | appendACLAtoms(targetPath, entry, type); | 1048 | appendACLAtoms(targetPath, entry, type); | ||
1016 | } | 1049 | } | ||
1017 | #endif | 1050 | #endif | ||
1018 | 1051 | | |||
1019 | if (details > 0) { | 1052 | if (details & KIO::User) { | ||
1020 | entry.fastInsert(KIO::UDSEntry::UDS_MODIFICATION_TIME, stat_mtime(buff)); | | |||
1021 | entry.fastInsert(KIO::UDSEntry::UDS_ACCESS_TIME, stat_atime(buff)); | | |||
1022 | #ifndef Q_OS_WIN | 1053 | #ifndef Q_OS_WIN | ||
1023 | entry.fastInsert(KIO::UDSEntry::UDS_USER, getUserName(KUserId(stat_uid(buff)))); | 1054 | entry.fastInsert(KIO::UDSEntry::UDS_USER, getUserName(KUserId(stat_uid(buff)))); | ||
1024 | entry.fastInsert(KIO::UDSEntry::UDS_GROUP, getGroupName(KGroupId(stat_gid(buff)))); | 1055 | entry.fastInsert(KIO::UDSEntry::UDS_GROUP, getGroupName(KGroupId(stat_gid(buff)))); | ||
1025 | #else | 1056 | #else | ||
1026 | #pragma message("TODO: st_uid and st_gid are always zero, use GetSecurityInfo to find the owner") | 1057 | #pragma message("TODO: st_uid and st_gid are always zero, use GetSecurityInfo to find the owner") | ||
1027 | #endif | 1058 | #endif | ||
1059 | } | ||||
1060 | | ||||
1061 | if (details & KIO::Time) { | ||||
1062 | entry.fastInsert(KIO::UDSEntry::UDS_MODIFICATION_TIME, stat_mtime(buff)); | ||||
1063 | entry.fastInsert(KIO::UDSEntry::UDS_ACCESS_TIME, stat_atime(buff)); | ||||
1028 | 1064 | | |||
1029 | #ifdef st_birthtime | 1065 | #ifdef st_birthtime | ||
1030 | /* For example FreeBSD's and NetBSD's stat contains a field for | 1066 | /* For example FreeBSD's and NetBSD's stat contains a field for | ||
1031 | * the inode birth time: st_birthtime | 1067 | * the inode birth time: st_birthtime | ||
1032 | * This however only works on UFS and ZFS, and not, on say, NFS. | 1068 | * This however only works on UFS and ZFS, and not, on say, NFS. | ||
1033 | * Instead of setting a bogus fallback like st_mtime, only use | 1069 | * Instead of setting a bogus fallback like st_mtime, only use | ||
1034 | * it if it is greater than 0. */ | 1070 | * it if it is greater than 0. */ | ||
1035 | if (buff.st_birthtime > 0) { | 1071 | if (buff.st_birthtime > 0) { | ||
▲ Show 20 Lines • Show All 522 Lines • Show Last 20 Lines |
int is actually faster on most CPUs, and reserve() will convert it to an int anyway, so it might as well be an int from the beginning.