Android应用中fstatat64系统调用用法及SD卡文件检测示例咨询
fstatat64 on Android to Detect Files/Folders on SD Card Hey there! I get it, finding solid docs on Android-specific syscalls can be tricky—let's walk through fstatat64 step by step, plus a working example to check files and folders on your SD card.
What is fstatat64?
fstatat64 is a 64-bit variant of the fstatat system call, which lets you retrieve metadata about a file or directory relative to an open directory file descriptor (instead of relying solely on absolute paths). This is super handy if you're working within a specific directory (like an SD card folder) and want to avoid constructing long, repetitive absolute paths every time.
Key perks over regular stat:
- You can pass
AT_FDCWDas the first argument to use the current process's working directory as the reference point. - It supports flags like
AT_SYMLINK_NOFOLLOWto get info about a symlink itself instead of following it to its target file.
Basic Usage Breakdown
The function signature (in C, since we're dealing with native syscalls on Android) looks like this:
#include <sys/stat.h> #include <fcntl.h> int fstatat64(int dirfd, const char *pathname, struct stat64 *buf, int flags);
Here's what each parameter does:
dirfd: File descriptor of an open directory (useAT_FDCWDto refer to the current process's working directory).pathname: Relative path to the file/folder you want to check (you can use an absolute path too, though that reduces some of the utility).buf: Pointer to astruct stat64where the file's metadata (size, type, modification time, etc.) will be stored.flags: Optional flags (common one:AT_SYMLINK_NOFOLLOWto skip resolving symlinks).
Example: Detect Files/Folders on SD Card
Let's put this into practice. This example will open an SD card directory, then use fstatat64 to check if a specific file and folder exist, and what type they are.
First, note that on Android, the primary shared storage path is usually /storage/emulated/0, while external SD cards have paths like /storage/XXXX-XXXX (where XXXX is a hexadecimal ID). Make sure your app has the READ_EXTERNAL_STORAGE permission (and for Android 13+, READ_MEDIA_IMAGES/READ_MEDIA_VIDEO/READ_MEDIA_AUDIO depending on what you're accessing).
Here's the code:
#include <stdio.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> int main() { // Path to the SD card directory we want to work with const char *sd_dir_path = "/storage/emulated/0/Documents"; // Target file and folder to check const char *target_file = "notes.txt"; const char *target_folder = "MyProjects"; // Open the SD card directory to get its file descriptor int dir_fd = open(sd_dir_path, O_RDONLY | O_DIRECTORY); if (dir_fd == -1) { perror("Failed to open SD directory"); return 1; } // Buffer to store file metadata struct stat64 file_stat; // Check the target file int result = fstatat64(dir_fd, target_file, &file_stat, 0); if (result == 0) { printf("Found file: %s\n", target_file); if (S_ISREG(file_stat.st_mode)) { printf(" It's a regular file, size: %lld bytes\n", (long long)file_stat.st_size); } else if (S_ISDIR(file_stat.st_mode)) { printf(" Wait, this is actually a directory!\n"); } } else { if (errno == ENOENT) { printf("File %s does not exist\n", target_file); } else { perror("Error checking file"); } } // Check the target folder result = fstatat64(dir_fd, target_folder, &file_stat, 0); if (result == 0) { printf("\nFound folder: %s\n", target_folder); if (S_ISDIR(file_stat.st_mode)) { printf(" It's a directory, last modified: %lld\n", (long long)file_stat.st_mtime); } else { printf(" Wait, this is actually a file!\n"); } } else { if (errno == ENOENT) { printf("Folder %s does not exist\n", target_folder); } else { perror("Error checking folder"); } } // Don't forget to close the directory descriptor! close(dir_fd); return 0; }
Key Notes for Android:
- Permissions: Your app must declare the appropriate storage permissions in the manifest and request them at runtime (for Android 6.0+).
- 64-bit Compatibility: Always use
stat64andfstatat64instead of their 32-bit counterparts—Android uses 64-bit inodes and file sizes, so 32-bit variants will fail on large files. - Partitioned Storage (Android 10+): If your app targets Android 10 or higher, you might need to use the MediaStore API for accessing media files, but
fstatat64still works for app-specific directories or if you enable legacy storage (though legacy storage isn't recommended for new apps).
Troubleshooting Tips
- If you get
EACCESerrors: Double-check your app's storage permissions, and make sure the SD card isn't mounted as read-only. - If paths don't work: Verify the exact SD card path (you can use
adb shell ls /storageto list available storage locations). - Symlinks: Use
AT_SYMLINK_NOFOLLOWin the flags if you want to check the symlink itself instead of its target.
内容的提问来源于stack exchange,提问作者user17795

