#ifndef PROC_MAPS_H_
#define PROC_MAPS_H_

#include <eztrace-core/eztrace_attributes.h>
#include <stdbool.h>
#include <sys/types.h>

/**
 * This struct can contain all the fields extracted from an entry in a /proc/.../maps file
 */
struct Maps_entry {
  int fields_count;
  void* stack_base_addr;
  void* stack_end_addr;
  char permissions[10];
  unsigned offset;
  unsigned device1;
  unsigned device2;
  int inode;
  char file[4096];
};

/**
 * Maps_entry_filter_func is a typedef on pointers on functions used to specify if a maps entry must be listed by the proc_maps.h functions
 */
typedef bool (*Maps_entry_filter_func)(struct Maps_entry const*);

bool maps_entry_filter_all(struct Maps_entry const* maps_entry);
bool maps_entry_filter_permissions(struct Maps_entry const* map_entry, char const* permissions);

/**
 * List all the mapped files in /proc/pid/maps under the form ":file1:file2:file3:" where "pid" is given by parameter
 * @param pid: the pid of the process to study
 * @param out: output buffer. Its original content is destroy and always replaced by a valid string, even if the function fails
 * @param out_size: output buffer size
 * @param filter: list of the permission needed ("w" implies write, "rx" implies read and exec, etc...)
 * @return 0 if successed, -1 if failed
 */
NODISCARD int get_mapped_file_names_in_proc_pid_maps(pid_t pid, char* out, int out_size,
                                                     Maps_entry_filter_func filter);
/**
 * List all the mapped files in /proc/name/maps under the form ":file1:file2:file3:" where "name" is given by parameter
 * @param name: name of the process to study
 * @param out: output buffer. Its original content is destroy and always replaced by a valid string, even if the function fails
 * @param out_size: output buffer size
 * @param filter: list of the permission needed ("w" implies write, "rx" implies read and exec, etc...)
 * @return 0 if successed, -1 if failed
 */
NODISCARD int get_mapped_file_names_in_proc_name_maps(char const* name, char* out, int out_size,
                                                      Maps_entry_filter_func filter);
/**
 * List all the mapped files in /proc/pid/maps under the form ":/path/to/file1:/path/to/file2:" where pid is given by parameter
 * @param pid: the pid of the process to study
 * @param out: output buffer. Its original content is destroy and always replaced by a valid string, even if the function fails
 * @param out_size: output buffer size
 * @param filter: list of the permission needed ("w" implies write, "rx" implies read and exec, etc...)
 * @return 0 if successed, -1 if failed
 */
NODISCARD int get_mapped_file_paths_in_proc_pid_maps(pid_t pid, char* out, int out_size,
                                                     Maps_entry_filter_func filter);
/**
 * List all the mapped files in /proc/name/maps under the form ":/path/to/file1:/path/to/file2:" where name is given by parameter
 * @param name: name of the process to study
 * @param out: output buffer. Its original content is destroy and always replaced by a valid string, even if the function fails
 * @param out_size: output buffer size
 * @param filter: list of the permission needed ("w" implies write, "rx" implies read and exec, etc...)
 * @return 0 if successed, -1 if failed
 */
NODISCARD int get_mapped_file_paths_in_proc_name_maps(char const* name, char* out, int out_size,
                                                      Maps_entry_filter_func filter);
/**
 * Parse /proc/pid/maps and return all entries in a array of _struct_entry where pid is given by parameter
 * @param pid: The pid of the process to study
 * @param maps_entries: The address of a pointer on _struct_entry. The pointer must be NULL and will be set to a newly allocated array of Maps_entry containing the result of the function. The pointer will stay at NULL if the function fails.
 * @param filter: a pointer on a function filter
 * @return The size of the out array, or -1 if the function failed
 */
NODISCARD int get_entries_in_proc_pid_maps(pid_t pid, struct Maps_entry** maps_entries,
                                           Maps_entry_filter_func filter);
/**
 * Parse /proc/name/maps and return all entries in a array of _struct_entry where name is given by parameter
 * @param name: the name of the process to study
 * @param maps_entries: The address of a pointer on _struct_entry. The pointer must be NULL and will be set to a newly allocated array of Maps_entry containing the result of the function. The pointer will stay at NULL if the function fails.
 * @param filter: a pointer on a function filter
 * @return The size of the out array, or -1 if the function failed
 */
NODISCARD int get_entries_in_proc_name_maps(char const* name, struct Maps_entry** maps_entries,
                                            Maps_entry_filter_func filter);

#endif // PROC_MAPS_H_

