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