Back to C++
2026-01-306 min read

File metadata (C++)

Learn File metadata (C++) step by step with clear examples and exercises.

Why This Matters

Understanding and manipulating file metadata in C++ is crucial for various applications such as system administration, digital forensics, data management, and even debugging issues. By knowing how to retrieve and modify file metadata, you can organize files more effectively, secure them, manage them efficiently, and gain insights into the behavior of your programs.

In real-world scenarios, being able to work with file metadata can help you:

  1. Troubleshoot issues related to file permissions or timestamps that might be causing problems in your applications or system.
  2. Write scripts for automating tasks like organizing files based on their creation or modification dates, or backing up important data at specific intervals.
  3. Perform digital forensics investigations by analyzing file metadata to gather evidence about when and how a file was created, modified, or accessed.
  4. Implement access controls in your applications by setting appropriate permissions for files based on user roles or permissions levels.

Prerequisites

To follow this lesson, you should have a basic understanding of:

  1. C++ programming fundamentals (variables, functions, loops, etc.)
  2. File I/O in C++ (reading and writing files)
  3. The concept of system calls
  4. Basic knowledge of operating systems (file systems, permissions, etc.)
  5. Familiarity with bitwise operations (optional but recommended for understanding file permissions)

Core Concept

In C++, you can work with file metadata using several libraries and system calls. Here we will focus on the stat function, which is part of the standard C library, as well as other functions like fstat, lstat, and getcwd.

Using stat

The stat function takes a file path as an argument and returns a struct stat containing various metadata properties. Here's a simple example:

#include <iostream>
#include <sys/stat.h>

int main() {
const char* filename = "example.txt";
struct stat file_info;

if (stat(filename, &file_info) == 0) {
std::cout << "File size: " << file_info.st_size << std::endl;
std::cout << "Last modification time: " << ctime(&file_info.st_mtime);
} else {
std::cerr << "Error reading file metadata." << std::endl;
}

return 0;
}

This program prints the size and last modification time of a file named example.txt. The st_size member of the struct stat holds the file size, while the st_mtime member contains the last modification time (in seconds since the epoch).

Common Metadata Properties

Here's a list of some common metadata properties that can be accessed using the stat function:

  1. File size: st_size
  2. Last access time: st_atime
  3. Last modification time: st_mtime
  4. Inode change time: st_ctime (the inode is a data structure used by the file system to store information about a file)
  5. File permissions: st_mode (can be converted into read, write, and execute permissions using bitwise operations)
  6. Link count: st_nlink (number of hard links to the file)
  7. Block size for files: st_blksize
  8. Number of blocks allocated to the file: st_blocks
  9. Device ID: st_dev (identifies the device where the file is located)
  10. Inode number: st_ino (unique identifier for each inode)

Using fstat and lstat

The fstat function is similar to stat, but it takes a file descriptor instead of a file path. This can be useful when working with open files. The lstat function works like stat, but it does not follow symbolic links. This means that if you call lstat on a symbolic link, it will return information about the link itself rather than the target file.

Getting current working directory (getcwd)

The getcwd function returns the current working directory as a null-terminated string. It can be useful for constructing file paths or listing files in the current directory.

Worked Example

Let's create a simple C++ program that reads metadata from a file, prints it, and then modifies the last modification time of the file.

#include <iostream>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
const char* filename = "example.txt";
struct stat file_info;
int fd;

// Read metadata from the file
if (stat(filename, &file_info) == 0) {
std::cout << "Original File Metadata:\n";
std::cout << "File size: " << file_info.st_size << std::endl;
std::cout << "Last modification time: " << ctime(&file_info.st_mtime);
} else {
std::cerr << "Error reading file metadata." << std::endl;
return 1;
}

// Open the file for writing
fd = open(filename, O_WRONLY | O_RDONLY);
if (fd == -1) {
std::cerr << "Error opening the file." << std::endl;
return 1;
}

// Modify last modification time of the file
struct utimbuf new_time = {0};
time_t now = time(NULL);
new_time.actime = file_info.st_atime;
new_time.modtime = now;
if (futimes(fd, &new_time) == -1) {
std::cerr << "Error modifying the last modification time." << std::endl;
close(fd);
return 1;
}

// Close the file
close(fd);

// Read metadata from the file again to verify the change
if (stat(filename, &file_info) == 0) {
std::cout << "\nModified File Metadata:\n";
std::cout << "File size: " << file_info.st_size << std::endl;
std::cout << "Last modification time: " << ctime(&file_info.st_mtime);
} else {
std::cerr << "Error reading modified file metadata." << std::endl;
return 1;
}

return 0;
}

Common Mistakes

  1. Forgetting to include necessary headers (e.g., `, , and `)
  2. Not checking the return value of system calls (e.g., stat, open, futimes) and handling errors appropriately
  3. Incorrectly interpreting file permissions using bitwise operations
  4. Not understanding the difference between fstat and lstat and using them inappropriately
  5. Failing to close open files after use (which can lead to resource leaks)

Practice Questions

  1. Write a program that reads the size, last access time, and last modification time of all files in the current directory.
  2. Modify the worked example to change the file's last access time instead of the last modification time.
  3. Write a program that checks if a given file exists and returns its permissions as read, write, and execute permissions for the owner, group, and others, respectively.
  4. Write a program that lists all files in the current directory, along with their sizes and last modification times.
  5. Modify the worked example to change the file's owner and group using the chown system call.

FAQ

  1. What is the purpose of the st_atime, st_mtime, and st_ctime members in the struct stat?
  • st_atime: Last time the file was accessed (read or executed)
  • st_mtime: Last time the file's contents were modified
  • st_ctime: Last time the inode associated with the file was changed (e.g., when the file is renamed, moved, or hard linked)
  1. What are some common uses of working with file metadata in C++?
  • Organizing files based on their creation or modification dates
  • Backing up important data at specific intervals
  • Digital forensics investigations
  • Implementing access controls in applications
  1. Why should I check the return value of system calls and handle errors appropriately?
  • System calls can fail for various reasons, such as incorrect arguments or permission issues. Handling these errors properly ensures that your program behaves correctly and doesn't crash unexpectedly.
  1. What is the difference between fstat and lstat in C++?
  • fstat takes a file descriptor as an argument and follows symbolic links if they exist, while lstat takes a file path and does not follow symbolic links. This means that if you call lstat on a symbolic link, it will return information about the link itself rather than the target file.
  1. Why is it important to close open files after use in C++?
  • Failing to close open files can lead to resource leaks, as the operating system may not be able to reuse the associated resources (such as file descriptors or memory) until the program terminates. Closing open files ensures that resources are freed and can be used by other processes.
File metadata (C++) | C++ | XQA Learn