2 #ifndef EL__UTIL_FILE_H
3 #define EL__UTIL_FILE_H
8 #include "util/string.h"
10 /** Data read about an entry in a directory.
11 * The strings pointed to by this structure are in the system
12 * charset (i.e. LC_CTYPE) and must be freed with mem_free(). */
13 struct directory_entry
{
14 /** The various attribute info collected with the @c stat_* functions. */
15 unsigned char *attrib
;
17 /** The full path of the dir entry. */
21 /** First information such as permissions is gathered for each directory entry.
22 * All entries are then sorted. */
23 struct directory_entry
*
24 get_directory_entries(unsigned char *dirname
, int get_hidden_files
);
26 int file_exists(const unsigned char *filename
);
27 int file_can_read(const unsigned char *filename
);
28 int file_is_dir(const unsigned char *filename
);
30 /** Strips all directory stuff from @a filename and returns the
31 * position of where the actual filename starts */
32 unsigned char *get_filename_position(unsigned char *filename
);
34 /** Tilde is only expanded for the current users homedir (~/).
35 * The returned file name is allocated. */
36 unsigned char *expand_tilde(unsigned char *filename
);
38 /*! @brief Generate a unique file name by trial and error based on the
39 * @a fileprefix by adding suffix counter (e.g. '.42').
41 * The returned file name is allocated if @a fileprefix is not unique. */
42 unsigned char *get_unique_name(unsigned char *fileprefix
);
44 /** Checks various environment variables to get the name of the temp dir.
45 * Returns a filename by concatenating "<tmpdir>/<name>". */
46 unsigned char *get_tempdir_filename(unsigned char *name
);
48 /** Read a line from @a file into the dynamically allocated @a line,
49 * increasing @a line if necessary. Ending whitespace is trimmed.
50 * If a line ends with "\" the next line is read too.
51 * If @a line is NULL the returned line is allocated and if file
52 * reading fails @a line is free()d. */
53 unsigned char *file_read_line(unsigned char *line
, size_t *linesize
,
54 FILE *file
, int *linenumber
);
56 /** Safe wrapper for mkstemp().
57 * It enforces permissions by calling umask(0177), call mkstemp(), then
58 * restore previous umask(). */
59 int safe_mkstemp(unsigned char *template);
61 /** Recursively create directories in @a path. The last element in the path is
62 * taken to be a filename, and simply ignored */
63 int mkalldirs(const unsigned char *path
);
65 /* comparison function for qsort() */
66 int compare_dir_entries(const void *v1
, const void *v2
);
69 /** @name The stat_* functions set the various attributes for directory entries.
73 stat_type(struct string
*string
, struct stat
*stp
)
75 unsigned char c
= '?';
78 if (S_ISDIR(stp
->st_mode
)) c
= 'd';
79 else if (S_ISREG(stp
->st_mode
)) c
= '-';
81 else if (S_ISBLK(stp
->st_mode
)) c
= 'b';
84 else if (S_ISCHR(stp
->st_mode
)) c
= 'c';
87 else if (S_ISFIFO(stp
->st_mode
)) c
= 'p';
90 else if (S_ISLNK(stp
->st_mode
)) c
= 'l';
93 else if (S_ISSOCK(stp
->st_mode
)) c
= 's';
96 else if (S_ISNWK(stp
->st_mode
)) c
= 'n';
100 add_char_to_string(string
, c
);
104 stat_mode(struct string
*string
, struct stat
*stp
)
106 #ifdef FS_UNIX_RIGHTS
107 unsigned char rwx
[10] = "---------";
110 mode_t mode
= stp
->st_mode
;
113 /* Set permissions attributes for user, group and other */
114 for (shift
= 0; shift
<= 6; shift
+= 3) {
115 mode_t m
= mode
<< shift
;
117 if (m
& S_IRUSR
) rwx
[shift
+ 0] = 'r';
118 if (m
& S_IWUSR
) rwx
[shift
+ 1] = 'w';
119 if (m
& S_IXUSR
) rwx
[shift
+ 2] = 'x';
124 rwx
[2] = (mode
& S_IXUSR
) ? 's' : 'S';
128 rwx
[5] = (mode
& S_IXGRP
) ? 's' : 'S';
132 rwx
[8] = (mode
& S_IXOTH
) ? 't' : 'T';
135 add_to_string(string
, rwx
);
137 add_char_to_string(string
, ' ');
141 stat_links(struct string
*string
, struct stat
*stp
)
143 #ifdef FS_UNIX_HARDLINKS
145 add_to_string(string
, " ");
147 unsigned char lnk
[64];
149 ulongcat(lnk
, NULL
, stp
->st_nlink
, 3, ' ');
150 add_to_string(string
, lnk
);
151 add_char_to_string(string
, ' ');
157 stat_user(struct string
*string
, struct stat
*stp
)
160 static unsigned char last_user
[64];
161 static int last_uid
= -1;
164 add_to_string(string
, " ");
168 if (stp
->st_uid
!= last_uid
) {
169 struct passwd
*pwd
= getpwuid(stp
->st_uid
);
171 if (!pwd
|| !pwd
->pw_name
)
172 /* ulongcat() can't pad from right. */
173 snprintf(last_user
, 64, "%-8d", (int) stp
->st_uid
);
175 snprintf(last_user
, 64, "%-8.8s", pwd
->pw_name
);
177 last_uid
= stp
->st_uid
;
180 add_to_string(string
, last_user
);
181 add_char_to_string(string
, ' ');
186 stat_group(struct string
*string
, struct stat
*stp
)
189 static unsigned char last_group
[64];
190 static int last_gid
= -1;
193 add_to_string(string
, " ");
197 if (stp
->st_gid
!= last_gid
) {
198 struct group
*grp
= getgrgid(stp
->st_gid
);
200 if (!grp
|| !grp
->gr_name
)
201 /* ulongcat() can't pad from right. */
202 snprintf(last_group
, 64, "%-8d", (int) stp
->st_gid
);
204 snprintf(last_group
, 64, "%-8.8s", grp
->gr_name
);
206 last_gid
= stp
->st_gid
;
209 add_to_string(string
, last_group
);
210 add_char_to_string(string
, ' ');
215 stat_size(struct string
*string
, struct stat
*stp
)
217 /* Check if st_size will cause overflow. */
218 /* FIXME: See bug 497 for info about support for big files. */
219 if (!stp
|| stp
->st_size
!= (unsigned long) stp
->st_size
) {
220 add_to_string(string
, " ");
223 unsigned char size
[64];
226 /* First try to fit the file size into 8 digits ... */
227 width
= ulongcat(size
, NULL
, stp
->st_size
, width
, ' ');
228 if (0 < width
&& width
< sizeof(size
)) {
229 /* ... if that is not enough expand the size buffer.
230 * This will only break the column alignment of the size
231 * attribute if really needed. */
232 ulongcat(size
, NULL
, stp
->st_size
, width
, ' ');
235 add_to_string(string
, size
);
236 add_char_to_string(string
, ' ');
241 stat_date(struct string
*string
, struct stat
*stp
)
245 time_t current_time
= time(NULL
);
246 time_t when
= stp
->st_mtime
;
249 if (current_time
> when
+ 6L * 30L * 24L * 60L * 60L
250 || current_time
< when
- 60L * 60L)
255 add_date_to_string(string
, fmt
, &when
);
256 add_char_to_string(string
, ' ');
260 add_to_string(string
, " ");