NeoMutt
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
file.h File Reference

File management functions. More...

#include "config.h"
#include <dirent.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/types.h>
+ Include dependency graph for file.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  timespec
 Time value with nanosecond precision. More...
 
struct  MuttFileIter
 State record for mutt_file_iter_line() More...
 

Macros

#define MUTT_RL_NO_FLAGS   0
 No flags are set.
 
#define MUTT_RL_CONT   (1 << 0)
 -continuation
 
#define MUTT_RL_EOL   (1 << 1)
 don't strip \n / \r\n
 

Typedefs

typedef uint8_t ReadLineFlags
 Flags for mutt_file_read_line(), e.g. MUTT_RL_CONT.
 
typedef bool(* mutt_file_map_t) (char *line, int line_num, void *user_data)
 

Enumerations

enum  MuttStatType { MUTT_STAT_ATIME , MUTT_STAT_MTIME , MUTT_STAT_CTIME }
 Flags for mutt_file_get_stat_timespec. More...
 
enum  MuttOpenDirMode { MUTT_OPENDIR_NONE , MUTT_OPENDIR_CREATE }
 Mode flag for mutt_file_opendir() More...
 

Functions

int mutt_file_check_empty (const char *path)
 Is the mailbox empty.
 
int mutt_file_chmod (const char *path, mode_t mode)
 Set permissions of a file.
 
int mutt_file_chmod_add (const char *path, mode_t mode)
 Add permissions to a file.
 
int mutt_file_chmod_add_stat (const char *path, mode_t mode, struct stat *st)
 Add permissions to a file.
 
int mutt_file_chmod_rm (const char *path, mode_t mode)
 Remove permissions from a file.
 
int mutt_file_chmod_rm_stat (const char *path, mode_t mode, struct stat *st)
 Remove permissions from a file.
 
int mutt_file_copy_bytes (FILE *fp_in, FILE *fp_out, size_t size)
 Copy some content from one file to another.
 
int mutt_file_copy_stream (FILE *fp_in, FILE *fp_out)
 Copy the contents of one file into another.
 
time_t mutt_file_decrease_mtime (const char *fp, struct stat *st)
 Decrease a file's modification time by 1 second.
 
void mutt_file_expand_fmt (struct Buffer *dest, const char *fmt, const char *src)
 Replace s in a string with a filename.
 
void mutt_file_expand_fmt_quote (char *dest, size_t destlen, const char *fmt, const char *src)
 
int mutt_file_fclose (FILE **fp)
 Close a FILE handle (and NULL the pointer)
 
FILE * mutt_file_fopen (const char *path, const char *mode)
 Call fopen() safely.
 
int mutt_file_fsync_close (FILE **fp)
 Flush the data, before closing a file (and NULL the pointer)
 
long mutt_file_get_size (const char *path)
 Get the size of a file.
 
long mutt_file_get_size_fp (FILE *fp)
 Get the size of a file.
 
void mutt_file_get_stat_timespec (struct timespec *dest, struct stat *st, enum MuttStatType type)
 Read the stat() time into a time value.
 
bool mutt_file_iter_line (struct MuttFileIter *iter, FILE *fp, ReadLineFlags flags)
 Iterate over the lines from an open file pointer.
 
int mutt_file_lock (int fd, bool excl, bool timeout)
 (Try to) Lock a file using fcntl()
 
bool mutt_file_map_lines (mutt_file_map_t func, void *user_data, FILE *fp, ReadLineFlags flags)
 Process lines of text read from a file pointer.
 
int mutt_file_mkdir (const char *path, mode_t mode)
 Recursively create directories.
 
int mutt_file_open (const char *path, uint32_t flags)
 Open a file.
 
DIR * mutt_file_opendir (const char *path, enum MuttOpenDirMode mode)
 Open a directory.
 
size_t mutt_file_quote_filename (const char *filename, char *buf, size_t buflen)
 Quote a filename to survive the shell's quoting rules.
 
char * mutt_file_read_keyword (const char *file, char *buf, size_t buflen)
 Read a keyword from a file.
 
char * mutt_file_read_line (char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
 Read a line from a file.
 
int mutt_file_rename (const char *oldfile, const char *newfile)
 Rename a file.
 
int mutt_file_rmtree (const char *path)
 Recursively remove a directory.
 
const char * mutt_file_rotate (const char *path, int num)
 Rotate a set of numbered files.
 
int mutt_file_safe_rename (const char *src, const char *target)
 NFS-safe renaming of files.
 
void mutt_file_sanitize_filename (char *path, bool slash)
 Replace unsafe characters in a filename.
 
int mutt_file_sanitize_regex (struct Buffer *dest, const char *src)
 Escape any regex-magic characters in a string.
 
bool mutt_file_seek (FILE *fp, LOFF_T offset, int whence)
 Wrapper for fseeko with error handling.
 
void mutt_file_set_mtime (const char *from, const char *to)
 Set the modification time of one file from another.
 
int mutt_file_stat_compare (struct stat *st1, enum MuttStatType st1_type, struct stat *st2, enum MuttStatType st2_type)
 Compare two stat infos.
 
int mutt_file_stat_timespec_compare (struct stat *st, enum MuttStatType type, struct timespec *b)
 Compare stat info with a time value.
 
int mutt_file_symlink (const char *oldpath, const char *newpath)
 Create a symlink.
 
int mutt_file_timespec_compare (struct timespec *a, struct timespec *b)
 Compare to time values.
 
void mutt_file_touch_atime (int fd)
 Set the access time to current time.
 
void mutt_file_unlink (const char *s)
 Delete a file, carefully.
 
void mutt_file_unlink_empty (const char *path)
 Delete a file if it's empty.
 
int mutt_file_unlock (int fd)
 Unlock a file previously locked by mutt_file_lock()
 
void mutt_file_resolve_symlink (struct Buffer *buf)
 Resolve a symlink in place.
 
void buf_quote_filename (struct Buffer *buf, const char *filename, bool add_outer)
 Quote a filename to survive the shell's quoting rules.
 
void buf_file_expand_fmt_quote (struct Buffer *dest, const char *fmt, const char *src)
 Replace s in a string with a filename.
 

Variables

const char FilenameSafeChars []
 Set of characters <=0x7F that are safe to use in filenames.
 

Detailed Description

File management functions.

Authors
  • Richard Russon

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file file.h.

Macro Definition Documentation

◆ MUTT_RL_NO_FLAGS

#define MUTT_RL_NO_FLAGS   0

No flags are set.

Definition at line 39 of file file.h.

◆ MUTT_RL_CONT

#define MUTT_RL_CONT   (1 << 0)

-continuation

Definition at line 40 of file file.h.

◆ MUTT_RL_EOL

#define MUTT_RL_EOL   (1 << 1)

don't strip \n / \r\n

Definition at line 41 of file file.h.

Typedef Documentation

◆ ReadLineFlags

typedef uint8_t ReadLineFlags

Flags for mutt_file_read_line(), e.g. MUTT_RL_CONT.

Definition at line 38 of file file.h.

◆ mutt_file_map_t

typedef bool(* mutt_file_map_t) (char *line, int line_num, void *user_data)

Definition at line 98 of file file.h.

Enumeration Type Documentation

◆ MuttStatType

Flags for mutt_file_get_stat_timespec.

These represent filesystem timestamps returned by stat()

Enumerator
MUTT_STAT_ATIME 

File/dir's atime - last accessed time.

MUTT_STAT_MTIME 

File/dir's mtime - last modified time.

MUTT_STAT_CTIME 

File/dir's ctime - creation time.

Definition at line 61 of file file.h.

62{
66};
@ MUTT_STAT_CTIME
File/dir's ctime - creation time.
Definition: file.h:65
@ MUTT_STAT_ATIME
File/dir's atime - last accessed time.
Definition: file.h:63
@ MUTT_STAT_MTIME
File/dir's mtime - last modified time.
Definition: file.h:64

◆ MuttOpenDirMode

Mode flag for mutt_file_opendir()

Enumerator
MUTT_OPENDIR_NONE 

Plain opendir()

MUTT_OPENDIR_CREATE 

Create the directory if it doesn't exist.

Definition at line 71 of file file.h.

72{
75};
@ MUTT_OPENDIR_CREATE
Create the directory if it doesn't exist.
Definition: file.h:74
@ MUTT_OPENDIR_NONE
Plain opendir()
Definition: file.h:73

Function Documentation

◆ mutt_file_check_empty()

int mutt_file_check_empty ( const char *  path)

Is the mailbox empty.

Parameters
pathPath to mailbox
Return values
1Mailbox is empty
0Mailbox is not empty
-1Error

Definition at line 1477 of file file.c.

1478{
1479 if (!path)
1480 return -1;
1481
1482 struct stat st = { 0 };
1483 if (stat(path, &st) == -1)
1484 return -1;
1485
1486 return st.st_size == 0;
1487}
+ Here is the caller graph for this function:

◆ mutt_file_chmod()

int mutt_file_chmod ( const char *  path,
mode_t  mode 
)

Set permissions of a file.

Parameters
pathFilename
modethe permissions to set
Return values
numSame as chmod(2)

This is essentially chmod(path, mode), see chmod(2).

Definition at line 1110 of file file.c.

1111{
1112 if (!path)
1113 return -1;
1114
1115 return chmod(path, mode);
1116}

◆ mutt_file_chmod_add()

int mutt_file_chmod_add ( const char *  path,
mode_t  mode 
)

Add permissions to a file.

Parameters
pathFilename
modethe permissions to add
Return values
numSame as chmod(2)

Adds the given permissions to the file. Permissions not mentioned in mode will stay as they are. This function resembles the chmod ugoa+rwxXst command family. Example:

mutt_file_chmod_add(path, S_IWUSR | S_IWGRP | S_IWOTH);

will add write permissions to path but does not alter read and other permissions.

See also
mutt_file_chmod_add_stat()

Definition at line 1135 of file file.c.

1136{
1137 return mutt_file_chmod_add_stat(path, mode, NULL);
1138}
int mutt_file_chmod_add_stat(const char *path, mode_t mode, struct stat *st)
Add permissions to a file.
Definition: file.c:1158
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_chmod_add_stat()

int mutt_file_chmod_add_stat ( const char *  path,
mode_t  mode,
struct stat *  st 
)

Add permissions to a file.

Parameters
pathFilename
modethe permissions to add
ststruct stat for the file (optional)
Return values
numSame as chmod(2)

Same as mutt_file_chmod_add() but saves a system call to stat() if a non-NULL stat structure is given. Useful if the stat structure of the file was retrieved before by the calling code. Example:

struct stat st;
stat(path, &st);
// ... do something else with st ...
mutt_file_chmod_add_stat(path, S_IWUSR | S_IWGRP | S_IWOTH, st);
See also
mutt_file_chmod_add()

Definition at line 1158 of file file.c.

1159{
1160 if (!path)
1161 return -1;
1162
1163 struct stat st2 = { 0 };
1164
1165 if (!st)
1166 {
1167 if (stat(path, &st2) == -1)
1168 return -1;
1169 st = &st2;
1170 }
1171 return chmod(path, st->st_mode | mode);
1172}
+ Here is the caller graph for this function:

◆ mutt_file_chmod_rm()

int mutt_file_chmod_rm ( const char *  path,
mode_t  mode 
)

Remove permissions from a file.

Parameters
pathFilename
modethe permissions to remove
Return values
numSame as chmod(2)

Removes the given permissions from the file. Permissions not mentioned in mode will stay as they are. This function resembles the chmod ugoa-rwxXst command family. Example:

mutt_file_chmod_rm(path, S_IWUSR | S_IWGRP | S_IWOTH);

will remove write permissions from path but does not alter read and other permissions.

See also
mutt_file_chmod_rm_stat()

Definition at line 1191 of file file.c.

1192{
1193 return mutt_file_chmod_rm_stat(path, mode, NULL);
1194}
int mutt_file_chmod_rm_stat(const char *path, mode_t mode, struct stat *st)
Remove permissions from a file.
Definition: file.c:1214
+ Here is the call graph for this function:

◆ mutt_file_chmod_rm_stat()

int mutt_file_chmod_rm_stat ( const char *  path,
mode_t  mode,
struct stat *  st 
)

Remove permissions from a file.

Parameters
pathFilename
modethe permissions to remove
ststruct stat for the file (optional)
Return values
numSame as chmod(2)

Same as mutt_file_chmod_rm() but saves a system call to stat() if a non-NULL stat structure is given. Useful if the stat structure of the file was retrieved before by the calling code. Example:

struct stat st;
stat(path, &st);
// ... do something else with st ...
mutt_file_chmod_rm_stat(path, S_IWUSR | S_IWGRP | S_IWOTH, st);
See also
mutt_file_chmod_rm()

Definition at line 1214 of file file.c.

1215{
1216 if (!path)
1217 return -1;
1218
1219 struct stat st2 = { 0 };
1220
1221 if (!st)
1222 {
1223 if (stat(path, &st2) == -1)
1224 return -1;
1225 st = &st2;
1226 }
1227 return chmod(path, st->st_mode & ~mode);
1228}
+ Here is the caller graph for this function:

◆ mutt_file_copy_bytes()

int mutt_file_copy_bytes ( FILE *  fp_in,
FILE *  fp_out,
size_t  size 
)

Copy some content from one file to another.

Parameters
fp_inSource file
fp_outDestination file
sizeMaximum number of bytes to copy
Return values
0Success
-1Error, see errno

Definition at line 232 of file file.c.

233{
234 if (!fp_in || !fp_out)
235 return -1;
236
237 while (size > 0)
238 {
239 char buf[2048] = { 0 };
240 size_t chunk = (size > sizeof(buf)) ? sizeof(buf) : size;
241 chunk = fread(buf, 1, chunk, fp_in);
242 if (chunk < 1)
243 break;
244 if (fwrite(buf, 1, chunk, fp_out) != chunk)
245 return -1;
246
247 size -= chunk;
248 }
249
250 if (fflush(fp_out) != 0)
251 return -1;
252 return 0;
253}
+ Here is the caller graph for this function:

◆ mutt_file_copy_stream()

int mutt_file_copy_stream ( FILE *  fp_in,
FILE *  fp_out 
)

Copy the contents of one file into another.

Parameters
fp_inSource file
fp_outDestination file
Return values
numSuccess, number of bytes copied
-1Error, see errno

Definition at line 262 of file file.c.

263{
264 if (!fp_in || !fp_out)
265 return -1;
266
267 size_t total = 0;
268 size_t l;
269 char buf[1024] = { 0 };
270
271 while ((l = fread(buf, 1, sizeof(buf), fp_in)) > 0)
272 {
273 if (fwrite(buf, 1, l, fp_out) != l)
274 return -1;
275 total += l;
276 }
277
278 if (fflush(fp_out) != 0)
279 return -1;
280 return total;
281}
+ Here is the caller graph for this function:

◆ mutt_file_decrease_mtime()

time_t mutt_file_decrease_mtime ( const char *  fp,
struct stat *  st 
)

Decrease a file's modification time by 1 second.

Parameters
fpFilename
ststruct stat for the file (optional)
Return values
numUpdated Unix mtime
-1Error, see errno

If a file's mtime is NOW, then set it to 1 second in the past.

Definition at line 1031 of file file.c.

1032{
1033 if (!fp)
1034 return -1;
1035
1036 struct utimbuf utim = { 0 };
1037 struct stat st2 = { 0 };
1038 time_t mtime;
1039
1040 if (!st)
1041 {
1042 if (stat(fp, &st2) == -1)
1043 return -1;
1044 st = &st2;
1045 }
1046
1047 mtime = st->st_mtime;
1048 if (mtime == mutt_date_now())
1049 {
1050 mtime -= 1;
1051 utim.actime = mtime;
1052 utim.modtime = mtime;
1053 int rc;
1054 do
1055 {
1056 rc = utime(fp, &utim);
1057 } while ((rc == -1) && (errno == EINTR));
1058
1059 if (rc == -1)
1060 return -1;
1061 }
1062
1063 return mtime;
1064}
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:446
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_expand_fmt()

void mutt_file_expand_fmt ( struct Buffer dest,
const char *  fmt,
const char *  src 
)

Replace s in a string with a filename.

Parameters
destBuffer for the result
fmtprintf-like format string
srcFilename to substitute

Definition at line 1512 of file file.c.

1513{
1514 if (!dest || !fmt || !src)
1515 return;
1516
1517 const char *p = NULL;
1518 bool found = false;
1519
1520 buf_reset(dest);
1521
1522 for (p = fmt; *p; p++)
1523 {
1524 if (*p == '%')
1525 {
1526 switch (p[1])
1527 {
1528 case '%':
1529 buf_addch(dest, *p++);
1530 break;
1531 case 's':
1532 found = true;
1533 buf_addstr(dest, src);
1534 p++;
1535 break;
1536 default:
1537 buf_addch(dest, *p);
1538 break;
1539 }
1540 }
1541 else
1542 {
1543 buf_addch(dest, *p);
1544 }
1545 }
1546
1547 if (!found)
1548 {
1549 buf_addch(dest, ' ');
1550 buf_addstr(dest, src);
1551 }
1552}
void buf_reset(struct Buffer *buf)
Reset an existing Buffer.
Definition: buffer.c:88
size_t buf_addch(struct Buffer *buf, char c)
Add a single character to a Buffer.
Definition: buffer.c:253
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:238
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_expand_fmt_quote()

void mutt_file_expand_fmt_quote ( char *  dest,
size_t  destlen,
const char *  fmt,
const char *  src 
)

◆ mutt_file_fclose()

int mutt_file_fclose ( FILE **  fp)

Close a FILE handle (and NULL the pointer)

Parameters
[out]fpFILE handle to close
Return values
0Success
EOFError, see errno

Definition at line 152 of file file.c.

153{
154 if (!fp || !*fp)
155 return 0;
156
157 int rc = fclose(*fp);
158 *fp = NULL;
159 return rc;
160}

◆ mutt_file_fopen()

FILE * mutt_file_fopen ( const char *  path,
const char *  mode 
)

Call fopen() safely.

Parameters
pathFilename
modeMode e.g. "r" readonly; "w" read-write
Return values
ptrFILE handle
NULLError, see errno

When opening files for writing, make sure the file doesn't already exist to avoid race conditions.

Definition at line 636 of file file.c.

637{
638 if (!path || !mode)
639 return NULL;
640
641 if (mode[0] == 'w')
642 {
643 uint32_t flags = O_CREAT | O_EXCL | O_NOFOLLOW;
644
645 if (mode[1] == '+')
646 flags |= O_RDWR;
647 else
648 flags |= O_WRONLY;
649
650 int fd = mutt_file_open(path, flags);
651 if (fd < 0)
652 return NULL;
653
654 return fdopen(fd, mode);
655 }
656 else
657 {
658 return fopen(path, mode);
659 }
660}
int mutt_file_open(const char *path, uint32_t flags)
Open a file.
Definition: file.c:551
#define O_NOFOLLOW
Definition: file.c:67
+ Here is the call graph for this function:

◆ mutt_file_fsync_close()

int mutt_file_fsync_close ( FILE **  fp)

Flush the data, before closing a file (and NULL the pointer)

Parameters
[out]fpFILE handle to close
Return values
0Success
EOFError, see errno

Definition at line 168 of file file.c.

169{
170 if (!fp || !*fp)
171 return 0;
172
173 int rc = 0;
174
175 if (fflush(*fp) || fsync(fileno(*fp)))
176 {
177 int save_errno = errno;
178 rc = -1;
180 errno = save_errno;
181 }
182 else
183 {
184 rc = mutt_file_fclose(fp);
185 }
186
187 return rc;
188}
int mutt_file_fclose(FILE **fp)
Close a FILE handle (and NULL the pointer)
Definition: file.c:152
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_get_size()

long mutt_file_get_size ( const char *  path)

Get the size of a file.

Parameters
pathFile to measure
Return values
numSize in bytes
0Error

Definition at line 1560 of file file.c.

1561{
1562 if (!path)
1563 return 0;
1564
1565 struct stat st = { 0 };
1566 if (stat(path, &st) != 0)
1567 return 0;
1568
1569 return st.st_size;
1570}
+ Here is the caller graph for this function:

◆ mutt_file_get_size_fp()

long mutt_file_get_size_fp ( FILE *  fp)

Get the size of a file.

Parameters
fpFILE* to measure
Return values
numSize in bytes
0Error

Definition at line 1578 of file file.c.

1579{
1580 if (!fp)
1581 return 0;
1582
1583 struct stat st = { 0 };
1584 if (fstat(fileno(fp), &st) != 0)
1585 return 0;
1586
1587 return st.st_size;
1588}
+ Here is the caller graph for this function:

◆ mutt_file_get_stat_timespec()

void mutt_file_get_stat_timespec ( struct timespec dest,
struct stat *  st,
enum MuttStatType  type 
)

Read the stat() time into a time value.

Parameters
destTime value to populate
ststat info
typeType of stat info to read, e.g. MUTT_STAT_ATIME

Definition at line 1620 of file file.c.

1621{
1622 if (!dest || !st)
1623 return;
1624
1625 dest->tv_sec = 0;
1626 dest->tv_nsec = 0;
1627
1628 switch (type)
1629 {
1630 case MUTT_STAT_ATIME:
1631 dest->tv_sec = st->st_atime;
1632#ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
1633 dest->tv_nsec = st->st_atim.tv_nsec;
1634#endif
1635 break;
1636 case MUTT_STAT_MTIME:
1637 dest->tv_sec = st->st_mtime;
1638#ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
1639 dest->tv_nsec = st->st_mtim.tv_nsec;
1640#endif
1641 break;
1642 case MUTT_STAT_CTIME:
1643 dest->tv_sec = st->st_ctime;
1644#ifdef HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC
1645 dest->tv_nsec = st->st_ctim.tv_nsec;
1646#endif
1647 break;
1648 }
1649}
long tv_nsec
Number of nanosecond, on top.
Definition: file.h:52
time_t tv_sec
Number of seconds since the epoch.
Definition: file.h:51
+ Here is the caller graph for this function:

◆ mutt_file_iter_line()

bool mutt_file_iter_line ( struct MuttFileIter iter,
FILE *  fp,
ReadLineFlags  flags 
)

Iterate over the lines from an open file pointer.

Parameters
iterState of iteration including ptr to line
fpFile pointer to read from
flagsSame as mutt_file_read_line()
Return values
trueData read
falseOn eof

This is a slightly cleaner interface for mutt_file_read_line() which avoids the eternal C loop initialization ugliness. Use like this:

struct MuttFileIter iter = { 0 };
while (mutt_file_iter_line(&iter, fp, flags))
{
do_stuff(iter.line, iter.line_num);
}
bool mutt_file_iter_line(struct MuttFileIter *iter, FILE *fp, ReadLineFlags flags)
Iterate over the lines from an open file pointer.
Definition: file.c:844
State record for mutt_file_iter_line()
Definition: file.h:81
char * line
the line data
Definition: file.h:82
int line_num
line number
Definition: file.h:84

Definition at line 844 of file file.c.

845{
846 if (!iter)
847 return false;
848
849 char *p = mutt_file_read_line(iter->line, &iter->size, fp, &iter->line_num, flags);
850 if (!p)
851 return false;
852 iter->line = p;
853 return true;
854}
char * mutt_file_read_line(char *line, size_t *size, FILE *fp, int *line_num, ReadLineFlags flags)
Read a line from a file.
Definition: file.c:763
size_t size
allocated size of line data
Definition: file.h:83
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_lock()

int mutt_file_lock ( int  fd,
bool  excl,
bool  timeout 
)

(Try to) Lock a file using fcntl()

Parameters
fdFile descriptor to file
exclIf true, try to lock exclusively
timeoutIf true, Retry MAX_LOCK_ATTEMPTS times
Return values
0Success
-1Failure

Use fcntl() to lock a file.

Use mutt_file_unlock() to unlock the file.

Definition at line 1243 of file file.c.

1244{
1245 struct stat st = { 0 }, prev_sb = { 0 };
1246 int count = 0;
1247 int attempt = 0;
1248
1249 struct flock lck = { 0 };
1250 lck.l_type = excl ? F_WRLCK : F_RDLCK;
1251 lck.l_whence = SEEK_SET;
1252
1253 while (fcntl(fd, F_SETLK, &lck) == -1)
1254 {
1255 mutt_debug(LL_DEBUG1, "fcntl errno %d\n", errno);
1256 if ((errno != EAGAIN) && (errno != EACCES))
1257 {
1258 mutt_perror("fcntl");
1259 return -1;
1260 }
1261
1262 if (fstat(fd, &st) != 0)
1263 st.st_size = 0;
1264
1265 if (count == 0)
1266 prev_sb = st;
1267
1268 /* only unlock file if it is unchanged */
1269 if ((prev_sb.st_size == st.st_size) && (++count >= (timeout ? MAX_LOCK_ATTEMPTS : 0)))
1270 {
1271 if (timeout)
1272 mutt_error(_("Timeout exceeded while attempting fcntl lock"));
1273 return -1;
1274 }
1275
1276 prev_sb = st;
1277
1278 mutt_message(_("Waiting for fcntl lock... %d"), ++attempt);
1279 sleep(1);
1280 }
1281
1282 return 0;
1283}
#define MAX_LOCK_ATTEMPTS
Definition: file.c:63
#define mutt_error(...)
Definition: logging2.h:92
#define mutt_message(...)
Definition: logging2.h:91
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
#define mutt_perror(...)
Definition: logging2.h:93
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
#define _(a)
Definition: message.h:28
+ Here is the caller graph for this function:

◆ mutt_file_map_lines()

bool mutt_file_map_lines ( mutt_file_map_t  func,
void *  user_data,
FILE *  fp,
ReadLineFlags  flags 
)

Process lines of text read from a file pointer.

Parameters
funcCallback function to call for each line, see mutt_file_map_t
user_dataArbitrary data passed to "func"
fpFile pointer to read from
flagsSame as mutt_file_read_line()
Return values
trueAll data mapped
false"func" returns false

Definition at line 865 of file file.c.

866{
867 if (!func || !fp)
868 return false;
869
870 struct MuttFileIter iter = { 0 };
871 while (mutt_file_iter_line(&iter, fp, flags))
872 {
873 if (!(*func)(iter.line, iter.line_num, user_data))
874 {
875 FREE(&iter.line);
876 return false;
877 }
878 }
879 return true;
880}
#define FREE(x)
Definition: memory.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_mkdir()

int mutt_file_mkdir ( const char *  path,
mode_t  mode 
)

Recursively create directories.

Parameters
pathDirectories to create
modePermissions for final directory
Return values
0Success
-1Error (errno set)

Create a directory, creating the parents if necessary. (like mkdir -p)

Note
The permissions are only set on the final directory. The permissions of any parent directories are determined by the umask. (This is how "mkdir -p" behaves)

Definition at line 977 of file file.c.

978{
979 if (!path || (*path == '\0'))
980 {
981 errno = EINVAL;
982 return -1;
983 }
984
985 errno = 0;
986 char tmp_path[PATH_MAX] = { 0 };
987 const size_t len = strlen(path);
988
989 if (len >= sizeof(tmp_path))
990 {
991 errno = ENAMETOOLONG;
992 return -1;
993 }
994
995 struct stat st = { 0 };
996 if ((stat(path, &st) == 0) && S_ISDIR(st.st_mode))
997 return 0;
998
999 /* Create a mutable copy */
1000 mutt_str_copy(tmp_path, path, sizeof(tmp_path));
1001
1002 for (char *p = tmp_path + 1; *p; p++)
1003 {
1004 if (*p != '/')
1005 continue;
1006
1007 /* Temporarily truncate the path */
1008 *p = '\0';
1009
1010 if ((mkdir(tmp_path, S_IRWXU | S_IRWXG | S_IRWXO) != 0) && (errno != EEXIST))
1011 return -1;
1012
1013 *p = '/';
1014 }
1015
1016 if ((mkdir(tmp_path, mode) != 0) && (errno != EEXIST))
1017 return -1;
1018
1019 return 0;
1020}
size_t mutt_str_copy(char *dest, const char *src, size_t dsize)
Copy a string into a buffer (guaranteeing NUL-termination)
Definition: string.c:653
#define PATH_MAX
Definition: mutt.h:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_open()

int mutt_file_open ( const char *  path,
uint32_t  flags 
)

Open a file.

Parameters
pathPathname to open
flagsFlags, e.g. O_EXCL
Return values
>0Success, file handle
-1Error

Definition at line 551 of file file.c.

552{
553 if (!path)
554 return -1;
555
556 int fd;
557 struct Buffer safe_file = buf_make(0);
558 struct Buffer safe_dir = buf_make(0);
559
560 if (flags & O_EXCL)
561 {
562 buf_alloc(&safe_file, PATH_MAX);
563 buf_alloc(&safe_dir, PATH_MAX);
564
565 if (mkwrapdir(path, &safe_file, &safe_dir) == -1)
566 {
567 fd = -1;
568 goto cleanup;
569 }
570
571 fd = open(buf_string(&safe_file), flags, 0600);
572 if (fd < 0)
573 {
574 rmdir(buf_string(&safe_dir));
575 goto cleanup;
576 }
577
578 /* NFS and I believe cygwin do not handle movement of open files well */
579 close(fd);
580 if (put_file_in_place(path, buf_string(&safe_file), buf_string(&safe_dir)) == -1)
581 {
582 fd = -1;
583 goto cleanup;
584 }
585 }
586
587 fd = open(path, flags & ~O_EXCL, 0600);
588 if (fd < 0)
589 goto cleanup;
590
591 /* make sure the file is not symlink */
592 struct stat st_old = { 0 };
593 struct stat st_new = { 0 };
594 if (((lstat(path, &st_old) < 0) || (fstat(fd, &st_new) < 0)) ||
595 !compare_stat(&st_old, &st_new))
596 {
597 close(fd);
598 fd = -1;
599 goto cleanup;
600 }
601
602cleanup:
603 buf_dealloc(&safe_file);
604 buf_dealloc(&safe_dir);
605
606 return fd;
607}
void buf_dealloc(struct Buffer *buf)
Release the memory allocated by a buffer.
Definition: buffer.c:389
struct Buffer buf_make(size_t size)
Make a new buffer on the stack.
Definition: buffer.c:70
void buf_alloc(struct Buffer *buf, size_t new_size)
Make sure a buffer can store at least new_size bytes.
Definition: buffer.c:349
static const char * buf_string(const struct Buffer *buf)
Convert a buffer to a const char * "string".
Definition: buffer.h:93
static bool compare_stat(struct stat *st_old, struct stat *st_new)
Compare the struct stat's of two files/dirs.
Definition: file.c:79
static int put_file_in_place(const char *path, const char *safe_file, const char *safe_dir)
Move a file into place.
Definition: file.c:136
static int mkwrapdir(const char *path, struct Buffer *newfile, struct Buffer *newdir)
Create a temporary directory next to a file name.
Definition: file.c:93
String manipulation buffer.
Definition: buffer.h:34
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_opendir()

DIR * mutt_file_opendir ( const char *  path,
enum MuttOpenDirMode  mode 
)

Open a directory.

Parameters
pathDirectory path
modeSee MuttOpenDirMode
Return values
ptrDIR handle
NULLError, see errno

Definition at line 616 of file file.c.

617{
618 if ((mode == MUTT_OPENDIR_CREATE) && (mutt_file_mkdir(path, S_IRWXU) == -1))
619 {
620 return NULL;
621 }
622 errno = 0;
623 return opendir(path);
624}
int mutt_file_mkdir(const char *path, mode_t mode)
Recursively create directories.
Definition: file.c:977
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_quote_filename()

size_t mutt_file_quote_filename ( const char *  filename,
char *  buf,
size_t  buflen 
)

Quote a filename to survive the shell's quoting rules.

Parameters
filenameString to convert
bufBuffer for the result
buflenLength of buffer
Return values
numBytes written to the buffer

From the Unix programming FAQ by way of Liviu.

Definition at line 891 of file file.c.

892{
893 if (!buf)
894 return 0;
895
896 if (!filename)
897 {
898 *buf = '\0';
899 return 0;
900 }
901
902 size_t j = 0;
903
904 /* leave some space for the trailing characters. */
905 buflen -= 6;
906
907 buf[j++] = '\'';
908
909 for (size_t i = 0; (j < buflen) && filename[i]; i++)
910 {
911 if ((filename[i] == '\'') || (filename[i] == '`'))
912 {
913 buf[j++] = '\'';
914 buf[j++] = '\\';
915 buf[j++] = filename[i];
916 buf[j++] = '\'';
917 }
918 else
919 {
920 buf[j++] = filename[i];
921 }
922 }
923
924 buf[j++] = '\'';
925 buf[j] = '\0';
926
927 return j;
928}
+ Here is the caller graph for this function:

◆ mutt_file_read_keyword()

char * mutt_file_read_keyword ( const char *  file,
char *  buf,
size_t  buflen 
)

Read a keyword from a file.

Parameters
fileFile to read
bufBuffer to store the keyword
buflenLength of the buf
Return values
ptrStart of the keyword

Read one line from the start of a file. Skip any leading whitespace and extract the first token.

Definition at line 1447 of file file.c.

1448{
1449 FILE *fp = mutt_file_fopen(file, "r");
1450 if (!fp)
1451 return NULL;
1452
1453 buf = fgets(buf, buflen, fp);
1454 mutt_file_fclose(&fp);
1455
1456 if (!buf)
1457 return NULL;
1458
1459 SKIPWS(buf);
1460 char *start = buf;
1461
1462 while ((*buf != '\0') && !isspace(*buf))
1463 buf++;
1464
1465 *buf = '\0';
1466
1467 return start;
1468}
FILE * mutt_file_fopen(const char *path, const char *mode)
Call fopen() safely.
Definition: file.c:636
#define SKIPWS(ch)
Definition: string2.h:45
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_read_line()

char * mutt_file_read_line ( char *  line,
size_t *  size,
FILE *  fp,
int *  line_num,
ReadLineFlags  flags 
)

Read a line from a file.

Parameters
[out]lineBuffer allocated on the head (optional)
[in]sizeLength of buffer
[in]fpFile to read
[out]line_numCurrent line number (optional)
[in]flagsFlags, e.g. MUTT_RL_CONT
Return values
ptrThe allocated string

Read a line from "fp" into the dynamically allocated "line", increasing "line" if necessary. The ending "\n" or "\r\n" is removed. If a line ends with "\", this char and the linefeed is removed, and the next line is read too.

Definition at line 763 of file file.c.

764{
765 if (!size || !fp)
766 return NULL;
767
768 size_t offset = 0;
769 char *ch = NULL;
770
771 if (!line)
772 {
773 *size = 256;
774 line = mutt_mem_malloc(*size);
775 }
776
777 while (true)
778 {
779 if (!fgets(line + offset, *size - offset, fp))
780 {
781 FREE(&line);
782 return NULL;
783 }
784 ch = strchr(line + offset, '\n');
785 if (ch)
786 {
787 if (line_num)
788 (*line_num)++;
789 if (flags & MUTT_RL_EOL)
790 return line;
791 *ch = '\0';
792 if ((ch > line) && (*(ch - 1) == '\r'))
793 *--ch = '\0';
794 if (!(flags & MUTT_RL_CONT) || (ch == line) || (*(ch - 1) != '\\'))
795 return line;
796 offset = ch - line - 1;
797 }
798 else
799 {
800 int c;
801 c = getc(fp); /* This is kind of a hack. We want to know if the
802 char at the current point in the input stream is EOF.
803 feof() will only tell us if we've already hit EOF, not
804 if the next character is EOF. So, we need to read in
805 the next character and manually check if it is EOF. */
806 if (c == EOF)
807 {
808 /* The last line of fp isn't \n terminated */
809 if (line_num)
810 (*line_num)++;
811 return line;
812 }
813 else
814 {
815 ungetc(c, fp); /* undo our damage */
816 /* There wasn't room for the line -- increase "line" */
817 offset = *size - 1; /* overwrite the terminating 0 */
818 *size += 256;
819 mutt_mem_realloc(&line, *size);
820 }
821 }
822 }
823}
#define MUTT_RL_CONT
-continuation
Definition: file.h:40
#define MUTT_RL_EOL
don't strip \n / \r\n
Definition: file.h:41
void * mutt_mem_malloc(size_t size)
Allocate memory on the heap.
Definition: memory.c:90
void mutt_mem_realloc(void *ptr, size_t size)
Resize a block of memory on the heap.
Definition: memory.c:114
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_rename()

int mutt_file_rename ( const char *  oldfile,
const char *  newfile 
)

Rename a file.

Parameters
oldfileOld filename
newfileNew filename
Return values
0Success
1Old file doesn't exist
2New file already exists
3Some other error
Note
on access(2) use No dangling symlink problems here due to mutt_file_fopen().

Definition at line 1412 of file file.c.

1413{
1414 if (!oldfile || !newfile)
1415 return -1;
1416 if (access(oldfile, F_OK) != 0)
1417 return 1;
1418 if (access(newfile, F_OK) == 0)
1419 return 2;
1420
1421 FILE *fp_old = fopen(oldfile, "r");
1422 if (!fp_old)
1423 return 3;
1424 FILE *fp_new = mutt_file_fopen(newfile, "w");
1425 if (!fp_new)
1426 {
1427 mutt_file_fclose(&fp_old);
1428 return 3;
1429 }
1430 mutt_file_copy_stream(fp_old, fp_new);
1431 mutt_file_fclose(&fp_new);
1432 mutt_file_fclose(&fp_old);
1433 mutt_file_unlink(oldfile);
1434 return 0;
1435}
int mutt_file_copy_stream(FILE *fp_in, FILE *fp_out)
Copy the contents of one file into another.
Definition: file.c:262
void mutt_file_unlink(const char *s)
Delete a file, carefully.
Definition: file.c:196
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_rmtree()

int mutt_file_rmtree ( const char *  path)

Recursively remove a directory.

Parameters
pathDirectory to delete
Return values
0Success
-1Error, see errno

Definition at line 461 of file file.c.

462{
463 if (!path)
464 return -1;
465
466 struct dirent *de = NULL;
467 struct stat st = { 0 };
468 int rc = 0;
469
470 DIR *dir = mutt_file_opendir(path, MUTT_OPENDIR_NONE);
471 if (!dir)
472 {
473 mutt_debug(LL_DEBUG1, "error opening directory %s\n", path);
474 return -1;
475 }
476
477 /* We avoid using the buffer pool for this function, because it
478 * invokes recursively to an unknown depth. */
479 struct Buffer cur = buf_make(PATH_MAX);
480
481 while ((de = readdir(dir)))
482 {
483 if ((mutt_str_equal(".", de->d_name)) || (mutt_str_equal("..", de->d_name)))
484 continue;
485
486 buf_printf(&cur, "%s/%s", path, de->d_name);
487 /* XXX make nonrecursive version */
488
489 if (stat(buf_string(&cur), &st) == -1)
490 {
491 rc = 1;
492 continue;
493 }
494
495 if (S_ISDIR(st.st_mode))
496 rc |= mutt_file_rmtree(buf_string(&cur));
497 else
498 rc |= unlink(buf_string(&cur));
499 }
500 closedir(dir);
501
502 rc |= rmdir(path);
503
504 buf_dealloc(&cur);
505 return rc;
506}
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:173
DIR * mutt_file_opendir(const char *path, enum MuttOpenDirMode mode)
Open a directory.
Definition: file.c:616
int mutt_file_rmtree(const char *path)
Recursively remove a directory.
Definition: file.c:461
bool mutt_str_equal(const char *a, const char *b)
Compare two strings.
Definition: string.c:798
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_rotate()

const char * mutt_file_rotate ( const char *  path,
int  count 
)

Rotate a set of numbered files.

Parameters
pathTemplate filename
countMaximum number of files
Return values
ptrName of the 0'th file

Given a template 'temp', rename files numbered 0 to (count-1).

Rename:

  • ...
  • temp1 -> temp2
  • temp0 -> temp1

Definition at line 521 of file file.c.

522{
523 if (!path)
524 return NULL;
525
526 struct Buffer *old_file = buf_pool_get();
527 struct Buffer *new_file = buf_pool_get();
528
529 /* rotate the old debug logs */
530 for (count -= 2; count >= 0; count--)
531 {
532 buf_printf(old_file, "%s%d", path, count);
533 buf_printf(new_file, "%s%d", path, count + 1);
534 (void) rename(buf_string(old_file), buf_string(new_file));
535 }
536
537 path = buf_strdup(old_file);
538 buf_pool_release(&old_file);
539 buf_pool_release(&new_file);
540
541 return path;
542}
char * buf_strdup(const struct Buffer *buf)
Copy a Buffer's string.
Definition: buffer.c:542
struct Buffer * buf_pool_get(void)
Get a Buffer from the pool.
Definition: pool.c:81
void buf_pool_release(struct Buffer **ptr)
Return a Buffer to the pool.
Definition: pool.c:94
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_safe_rename()

int mutt_file_safe_rename ( const char *  src,
const char *  target 
)

NFS-safe renaming of files.

Parameters
srcOriginal filename
targetNew filename
Return values
0Success
-1Error, see errno

Warning: We don't check whether src and target are equal.

Definition at line 346 of file file.c.

347{
348 struct stat st_src = { 0 };
349 struct stat st_target = { 0 };
350 int link_errno;
351
352 if (!src || !target)
353 return -1;
354
355 if (link(src, target) != 0)
356 {
357 link_errno = errno;
358
359 /* It is historically documented that link can return -1 if NFS
360 * dies after creating the link. In that case, we are supposed
361 * to use stat to check if the link was created.
362 *
363 * Derek Martin notes that some implementations of link() follow a
364 * source symlink. It might be more correct to use stat() on src.
365 * I am not doing so to minimize changes in behavior: the function
366 * used lstat() further below for 20 years without issue, and I
367 * believe was never intended to be used on a src symlink. */
368 if ((lstat(src, &st_src) == 0) && (lstat(target, &st_target) == 0) &&
369 (compare_stat(&st_src, &st_target) == 0))
370 {
371 mutt_debug(LL_DEBUG1, "link (%s, %s) reported failure: %s (%d) but actually succeeded\n",
372 src, target, strerror(errno), errno);
373 goto success;
374 }
375
376 errno = link_errno;
377
378 /* Coda does not allow cross-directory links, but tells
379 * us it's a cross-filesystem linking attempt.
380 *
381 * However, the Coda rename call is allegedly safe to use.
382 *
383 * With other file systems, rename should just fail when
384 * the files reside on different file systems, so it's safe
385 * to try it here. */
386 mutt_debug(LL_DEBUG1, "link (%s, %s) failed: %s (%d)\n", src, target,
387 strerror(errno), errno);
388
389 /* FUSE may return ENOSYS. VFAT may return EPERM. FreeBSD's
390 * msdosfs may return EOPNOTSUPP. ENOTSUP can also appear. */
391 if ((errno == EXDEV) || (errno == ENOSYS) || errno == EPERM
392#ifdef ENOTSUP
393 || errno == ENOTSUP
394#endif
395#ifdef EOPNOTSUPP
396 || errno == EOPNOTSUPP
397#endif
398 )
399 {
400 mutt_debug(LL_DEBUG1, "trying rename\n");
401 if (rename(src, target) == -1)
402 {
403 mutt_debug(LL_DEBUG1, "rename (%s, %s) failed: %s (%d)\n", src, target,
404 strerror(errno), errno);
405 return -1;
406 }
407 mutt_debug(LL_DEBUG1, "rename succeeded\n");
408
409 return 0;
410 }
411
412 return -1;
413 }
414
415 /* Remove the compare_stat() check, because it causes problems with maildir
416 * on filesystems that don't properly support hard links, such as sshfs. The
417 * filesystem creates the link, but the resulting file is given a different
418 * inode number by the sshfs layer. This results in an infinite loop
419 * creating links. */
420#if 0
421 /* Stat both links and check if they are equal. */
422 if (lstat(src, &st_src) == -1)
423 {
424 mutt_debug(LL_DEBUG1, "#1 can't stat %s: %s (%d)\n", src, strerror(errno), errno);
425 return -1;
426 }
427
428 if (lstat(target, &st_target) == -1)
429 {
430 mutt_debug(LL_DEBUG1, "#2 can't stat %s: %s (%d)\n", src, strerror(errno), errno);
431 return -1;
432 }
433
434 /* pretend that the link failed because the target file did already exist. */
435
436 if (!compare_stat(&st_src, &st_target))
437 {
438 mutt_debug(LL_DEBUG1, "stat blocks for %s and %s diverge; pretending EEXIST\n", src, target);
439 errno = EEXIST;
440 return -1;
441 }
442#endif
443
444success:
445 /* Unlink the original link.
446 * Should we really ignore the return value here? XXX */
447 if (unlink(src) == -1)
448 {
449 mutt_debug(LL_DEBUG1, "unlink (%s) failed: %s (%d)\n", src, strerror(errno), errno);
450 }
451
452 return 0;
453}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_sanitize_filename()

void mutt_file_sanitize_filename ( char *  path,
bool  slash 
)

Replace unsafe characters in a filename.

Parameters
pathFilename to make safe
slashReplace '/' characters too

Definition at line 667 of file file.c.

668{
669 if (!path)
670 return;
671
672 size_t size = strlen(path);
673
674 wchar_t c;
675 mbstate_t mbstate = { 0 };
676 for (size_t consumed; size && (consumed = mbrtowc(&c, path, size, &mbstate));
677 size -= consumed, path += consumed)
678 {
679 switch (consumed)
680 {
682 mbstate = (mbstate_t){ 0 };
683 consumed = 1;
684 memset(path, '_', consumed);
685 break;
686
688 consumed = size;
689 memset(path, '_', consumed);
690 break;
691
692 default:
693 if ((slash && (c == L'/')) || ((c <= 0x7F) && !strchr(FilenameSafeChars, c)))
694 {
695 memset(path, '_', consumed);
696 }
697 break;
698 }
699 }
700}
const char FilenameSafeChars[]
Set of characters <=0x7F that are safe to use in filenames.
Definition: file.c:61
#define ICONV_BUF_TOO_SMALL
Error value for iconv() - Buffer too small.
Definition: charset.h:105
#define ICONV_ILLEGAL_SEQ
Error value for iconv() - Illegal sequence.
Definition: charset.h:103
+ Here is the caller graph for this function:

◆ mutt_file_sanitize_regex()

int mutt_file_sanitize_regex ( struct Buffer dest,
const char *  src 
)

Escape any regex-magic characters in a string.

Parameters
destBuffer for result
srcString to transform
Return values
0Success
-1Error

Definition at line 709 of file file.c.

710{
711 if (!dest || !src)
712 return -1;
713
714 buf_reset(dest);
715 while (*src != '\0')
716 {
717 if (strchr(RxSpecialChars, *src))
718 buf_addch(dest, '\\');
719 buf_addch(dest, *src++);
720 }
721
722 return 0;
723}
static const char RxSpecialChars[]
These characters must be escaped in regular expressions.
Definition: file.c:58
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_seek()

bool mutt_file_seek ( FILE *  fp,
LOFF_T  offset,
int  whence 
)

Wrapper for fseeko with error handling.

Parameters
[in]fpFile to seek
[in]offsetOffset
[in]whenceSeek mode
Return values
trueSeek was successful
falseSeek failed

Definition at line 733 of file file.c.

734{
735 if (!fp)
736 {
737 return false;
738 }
739
740 if (fseeko(fp, offset, whence) != 0)
741 {
742 mutt_perror(_("Failed to seek file: %s"), strerror(errno));
743 return false;
744 }
745
746 return true;
747}
+ Here is the caller graph for this function:

◆ mutt_file_set_mtime()

void mutt_file_set_mtime ( const char *  from,
const char *  to 
)

Set the modification time of one file from another.

Parameters
fromFilename whose mtime should be copied
toFilename to update

Definition at line 1071 of file file.c.

1072{
1073 if (!from || !to)
1074 return;
1075
1076 struct utimbuf utim = { 0 };
1077 struct stat st = { 0 };
1078
1079 if (stat(from, &st) != -1)
1080 {
1081 utim.actime = st.st_mtime;
1082 utim.modtime = st.st_mtime;
1083 utime(to, &utim);
1084 }
1085}
+ Here is the caller graph for this function:

◆ mutt_file_stat_compare()

int mutt_file_stat_compare ( struct stat *  st1,
enum MuttStatType  st1_type,
struct stat *  st2,
enum MuttStatType  st2_type 
)

Compare two stat infos.

Parameters
st1First stat info
st1_typeType of first stat info, e.g. MUTT_STAT_ATIME
st2Second stat info
st2_typeType of second stat info, e.g. MUTT_STAT_ATIME
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 1682 of file file.c.

1684{
1685 if (!st1 || !st2)
1686 return 0;
1687
1688 struct timespec a = { 0 };
1689 struct timespec b = { 0 };
1690
1691 mutt_file_get_stat_timespec(&a, st1, st1_type);
1692 mutt_file_get_stat_timespec(&b, st2, st2_type);
1693 return mutt_file_timespec_compare(&a, &b);
1694}
void mutt_file_get_stat_timespec(struct timespec *dest, struct stat *st, enum MuttStatType type)
Read the stat() time into a time value.
Definition: file.c:1620
int mutt_file_timespec_compare(struct timespec *a, struct timespec *b)
Compare to time values.
Definition: file.c:1598
Time value with nanosecond precision.
Definition: file.h:50
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_stat_timespec_compare()

int mutt_file_stat_timespec_compare ( struct stat *  st,
enum MuttStatType  type,
struct timespec b 
)

Compare stat info with a time value.

Parameters
ststat info
typeType of stat info, e.g. MUTT_STAT_ATIME
bTime value
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 1660 of file file.c.

1662{
1663 if (!st || !b)
1664 return 0;
1665
1666 struct timespec a = { 0 };
1667
1668 mutt_file_get_stat_timespec(&a, st, type);
1669 return mutt_file_timespec_compare(&a, b);
1670}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_symlink()

int mutt_file_symlink ( const char *  oldpath,
const char *  newpath 
)

Create a symlink.

Parameters
oldpathExisting pathname
newpathNew pathname
Return values
0Success
-1Error, see errno

Definition at line 290 of file file.c.

291{
292 struct stat st_old = { 0 };
293 struct stat st_new = { 0 };
294
295 if (!oldpath || !newpath)
296 return -1;
297
298 if ((unlink(newpath) == -1) && (errno != ENOENT))
299 return -1;
300
301 if (oldpath[0] == '/')
302 {
303 if (symlink(oldpath, newpath) == -1)
304 return -1;
305 }
306 else
307 {
308 struct Buffer abs_oldpath = buf_make(PATH_MAX);
309
310 if (!mutt_path_getcwd(&abs_oldpath))
311 {
312 buf_dealloc(&abs_oldpath);
313 return -1;
314 }
315
316 buf_addch(&abs_oldpath, '/');
317 buf_addstr(&abs_oldpath, oldpath);
318 if (symlink(buf_string(&abs_oldpath), newpath) == -1)
319 {
320 buf_dealloc(&abs_oldpath);
321 return -1;
322 }
323
324 buf_dealloc(&abs_oldpath);
325 }
326
327 if ((stat(oldpath, &st_old) == -1) || (stat(newpath, &st_new) == -1) ||
328 !compare_stat(&st_old, &st_new))
329 {
330 unlink(newpath);
331 return -1;
332 }
333
334 return 0;
335}
const char * mutt_path_getcwd(struct Buffer *cwd)
Get the current working directory.
Definition: path.c:571
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_timespec_compare()

int mutt_file_timespec_compare ( struct timespec a,
struct timespec b 
)

Compare to time values.

Parameters
aFirst time value
bSecond time value
Return values
-1a precedes b
0a and b are identical
1b precedes a

Definition at line 1598 of file file.c.

1599{
1600 if (!a || !b)
1601 return 0;
1602 if (a->tv_sec < b->tv_sec)
1603 return -1;
1604 if (a->tv_sec > b->tv_sec)
1605 return 1;
1606
1607 if (a->tv_nsec < b->tv_nsec)
1608 return -1;
1609 if (a->tv_nsec > b->tv_nsec)
1610 return 1;
1611 return 0;
1612}
+ Here is the caller graph for this function:

◆ mutt_file_touch_atime()

void mutt_file_touch_atime ( int  fd)

Set the access time to current time.

Parameters
fdFile descriptor of the file to alter

This is just as read() would do on !noatime. Silently ignored if futimens() isn't supported.

Definition at line 1094 of file file.c.

1095{
1096#ifdef HAVE_FUTIMENS
1097 struct timespec times[2] = { { 0, UTIME_NOW }, { 0, UTIME_OMIT } };
1098 futimens(fd, times);
1099#endif
1100}
+ Here is the caller graph for this function:

◆ mutt_file_unlink()

void mutt_file_unlink ( const char *  s)

Delete a file, carefully.

Parameters
sFilename

This won't follow symlinks.

Definition at line 196 of file file.c.

197{
198 if (!s)
199 return;
200
201 struct stat st = { 0 };
202 /* Defend against symlink attacks */
203
204 const bool is_regular_file = (lstat(s, &st) == 0) && S_ISREG(st.st_mode);
205 if (!is_regular_file)
206 return;
207
208 const int fd = open(s, O_RDWR | O_NOFOLLOW);
209 if (fd < 0)
210 return;
211
212 struct stat st2 = { 0 };
213 if ((fstat(fd, &st2) != 0) || !S_ISREG(st2.st_mode) ||
214 (st.st_dev != st2.st_dev) || (st.st_ino != st2.st_ino))
215 {
216 close(fd);
217 return;
218 }
219
220 unlink(s);
221 close(fd);
222}
+ Here is the caller graph for this function:

◆ mutt_file_unlink_empty()

void mutt_file_unlink_empty ( const char *  path)

Delete a file if it's empty.

Parameters
pathFile to delete

Definition at line 1376 of file file.c.

1377{
1378 if (!path)
1379 return;
1380
1381 struct stat st = { 0 };
1382
1383 int fd = open(path, O_RDWR);
1384 if (fd == -1)
1385 return;
1386
1387 if (mutt_file_lock(fd, true, true) == -1)
1388 {
1389 close(fd);
1390 return;
1391 }
1392
1393 if ((fstat(fd, &st) == 0) && (st.st_size == 0))
1394 unlink(path);
1395
1396 mutt_file_unlock(fd);
1397 close(fd);
1398}
int mutt_file_lock(int fd, bool excl, bool timeout)
(Try to) Lock a file using fcntl()
Definition: file.c:1243
int mutt_file_unlock(int fd)
Unlock a file previously locked by mutt_file_lock()
Definition: file.c:1290
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_file_unlock()

int mutt_file_unlock ( int  fd)

Unlock a file previously locked by mutt_file_lock()

Parameters
fdFile descriptor to file
Return values
0Always

Definition at line 1290 of file file.c.

1291{
1292 struct flock unlockit = { 0 };
1293 unlockit.l_type = F_UNLCK;
1294 unlockit.l_whence = SEEK_SET;
1295 (void) fcntl(fd, F_SETLK, &unlockit);
1296
1297 return 0;
1298}
+ Here is the caller graph for this function:

◆ mutt_file_resolve_symlink()

void mutt_file_resolve_symlink ( struct Buffer buf)

Resolve a symlink in place.

Parameters
bufInput/output path

Definition at line 1700 of file file.c.

1701{
1702 struct stat st = { 0 };
1703 int rc = lstat(buf_string(buf), &st);
1704 if ((rc != -1) && S_ISLNK(st.st_mode))
1705 {
1706 char path[PATH_MAX] = { 0 };
1707 if (realpath(buf_string(buf), path))
1708 {
1709 buf_strcpy(buf, path);
1710 }
1711 }
1712}
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:407
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ buf_quote_filename()

void buf_quote_filename ( struct Buffer buf,
const char *  filename,
bool  add_outer 
)

Quote a filename to survive the shell's quoting rules.

Parameters
bufBuffer for the result
filenameString to convert
add_outerIf true, add 'single quotes' around the result

Definition at line 936 of file file.c.

937{
938 if (!buf || !filename)
939 return;
940
941 buf_reset(buf);
942 if (add_outer)
943 buf_addch(buf, '\'');
944
945 for (; *filename != '\0'; filename++)
946 {
947 if ((*filename == '\'') || (*filename == '`'))
948 {
949 buf_addch(buf, '\'');
950 buf_addch(buf, '\\');
951 buf_addch(buf, *filename);
952 buf_addch(buf, '\'');
953 }
954 else
955 {
956 buf_addch(buf, *filename);
957 }
958 }
959
960 if (add_outer)
961 buf_addch(buf, '\'');
962}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ buf_file_expand_fmt_quote()

void buf_file_expand_fmt_quote ( struct Buffer dest,
const char *  fmt,
const char *  src 
)

Replace s in a string with a filename.

Parameters
destBuffer for the result
fmtprintf-like format string
srcFilename to substitute

This function also quotes the file to prevent shell problems.

Definition at line 1497 of file file.c.

1498{
1499 struct Buffer tmp = buf_make(PATH_MAX);
1500
1501 buf_quote_filename(&tmp, src, true);
1502 mutt_file_expand_fmt(dest, fmt, buf_string(&tmp));
1503 buf_dealloc(&tmp);
1504}
void buf_quote_filename(struct Buffer *buf, const char *filename, bool add_outer)
Quote a filename to survive the shell's quoting rules.
Definition: file.c:936
void mutt_file_expand_fmt(struct Buffer *dest, const char *fmt, const char *src)
Replace s in a string with a filename.
Definition: file.c:1512
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ FilenameSafeChars

const char FilenameSafeChars[]
extern

Set of characters <=0x7F that are safe to use in filenames.

Definition at line 61 of file file.c.