clsync
Loading...
Searching...
No Matches
fileutils.c
Go to the documentation of this file.
1/*
2 clsync - file tree sync utility based on inotify
3
4 Copyright (C) 2013 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "common.h"
21
22#include "error.h"
23#include "malloc.h"
24
25
26char *fd2fpath_malloc ( int fd )
27{
28#if __linux__
29 stat64_t st64;
30
31 if ( fd <= 0 ) {
32 error ( "Invalid file descriptor supplied: fd2fpath_malloc(%i).", fd );
33 errno = EINVAL;
34 return NULL;
35 }
36
37 char *fsym = xmalloc ( ( 1 << 8 ) + 2 );
38 sprintf ( fsym, "/proc/self/fd/%i", fd );
39
40 if ( lstat64 ( fsym, &st64 ) ) {
41 error ( "Cannot lstat64(\"%s\", st64).", fsym );
42 return NULL;
43 }
44
45 ssize_t fpathlen = st64.st_size;
46
47 char *fpath = xmalloc ( fpathlen + 2 );
48
49 debug ( 3, "Getting file path from symlink \"%s\". Path length is: %i.", fsym, fpathlen );
50
51 if ( ( fpathlen = readlink ( fsym, fpath, fpathlen + 1 ) ) < 0 ) {
52 error ( "Cannot readlink(\"%s\", fpath, bufsize).", fsym );
53 free(fsym);
54 return NULL;
55 }
56
57 fpath[fpathlen] = 0;
58 debug ( 3, "The path is: \"%s\"", fpath );
59 free(fsym);
60 return fpath;
61#else
62 critical ( "Function fd2fpath_malloc() is not supported in this OS" );
63 return NULL;
64#endif
65}
66
67/**
68 * @brief Copies file
69 *
70 * @param[in] path_from Source file path
71 * @param[in] path_to Destination file path
72 *
73 * @retval zero Successfully copied
74 * @retval non-zero Got error, while copying
75 *
76 */
77
78int fileutils_copy ( const char *path_from, const char *path_to )
79{
80 char buf[BUFSIZ];
81 FILE *from, *to;
82 from = fopen ( path_from, "r" );
83
84 if ( from == NULL ) {
85 error ( "fileutils_copy(\"%s\", \"%s\"): Cannot open file \"%s\" for reading",
86 path_from, path_to, path_from );
87 return errno;
88 }
89
90 to = fopen ( path_to, "w" );
91
92 if ( to == NULL ) {
93 error ( "fileutils_copy(\"%s\", \"%s\"): Cannot open file \"%s\" for writing",
94 path_from, path_to, path_to );
95 return errno;
96 }
97
98 while ( !feof ( from ) ) {
99 int err;
100 size_t r, w;
101 r = fread ( buf, 1, BUFSIZ, from );
102
103 if ( ( err = ferror ( from ) ) ) {
104 error ( "fileutils_copy(\"%s\", \"%s\"): Cannot read from file \"%s\"",
105 path_from, path_to, path_from );
106 return errno; // CHECK: Is the "errno" should be used in fread() case?
107 }
108
109 w = fwrite ( buf, 1, r, to );
110
111 if ( ( err = ferror ( to ) ) ) {
112 error ( "fileutils_copy(\"%s\", \"%s\"): Cannot write to file \"%s\"",
113 path_from, path_to, path_to );
114 return errno; // CHECK: is the "errno" should be used in fwrite() case?
115 }
116
117 if ( r != w ) {
118 error ( "fileutils_copy(\"%s\", \"%s\"): Got error while writing to file \"%s\" (%u != %u)",
119 path_from, path_to, path_to, r, w );
120 return errno; // CHECK: is the "errno" should be used in case "r != w"?
121 }
122 }
123
124 return 0;
125}
126
127
128/**
129 * @brief Calculates directory level of a canonized path (actually it just counts "/"-s)
130 *
131 * @param[in] path Canonized path (with realpath())
132 *
133 * @retval zero or prositive Direcory level
134 * @retval negative Got error, while calculation. Error-code is placed to errno.
135 *
136 */
137
138short int fileutils_calcdirlevel ( const char *path )
139{
140 short int dirlevel = 0;
141 const char *ptr = path;
142
143 if ( path == NULL ) {
144 error ( "path is NULL." );
145 errno = EINVAL;
146 return -1;
147 }
148
149 if ( *path == 0 ) {
150 error ( "path has zero length." );
151 errno = EINVAL;
152 return -2;
153 }
154
155 if ( *path != '/' ) {
156 error ( "path \"%s\" is not canonized.", path );
157 errno = EINVAL;
158 return -3;
159 }
160
161 while ( * ( ptr++ ) )
162 if ( *ptr == '/' )
163 dirlevel++;
164
165 return dirlevel;
166}
167
168/**
169 * @brief Combination of mkdirat() and openat()
170 *
171 * @param[in] dir_path Path to directory to create and open
172 * @param[in] dirfd_parent File descriptor of directory for relative paths
173 * @param[in] dir_mode Modes for newly created directory (e.g. 750)
174 *
175 * @retval dirfd File descriptor to newly created directory
176 * @retval NULL On error
177 *
178 */
179int mkdirat_open ( const char *const dir_path, int dirfd_parent, mode_t dir_mode )
180{
181 int dirfd;
182 debug ( 5, "mkdirat(%u, \"%s\", %o)", dirfd_parent, dir_path, dir_mode );
183
184 if ( mkdirat ( dirfd_parent, dir_path, dir_mode ) )
185 return -1;
186
187 debug ( 5, "openat(%u, \"%s\", %x)", dirfd_parent, dir_path, O_RDWR | O_DIRECTORY | O_PATH );
188 dirfd = openat ( dirfd_parent, dir_path, O_RDWR | O_DIRECTORY | O_PATH );
189
190 if ( dirfd == -1 )
191 return -1;
192
193 return dirfd;
194}
195
196/*
197 * @brief Opens a directory with open()
198 *
199 * @param[out] fd_p Pointer to the result file descriptor
200 * @param[in] dir_path Path to the directory
201 *
202 * @retval *fd_p On success
203 * @retval -1 On error
204 *
205 * /
206int open_dir(int *fd_p, const char *const dir_path) {
207 int fd = open(dir_path, O_RDONLY|O_DIRECTORY|O_PATH);
208 if (fd == -1) {
209 error("Got error while open(\"%s\", O_RDWR|O_DIRECTORY|O_PATH)", dir_path);
210 return fd;
211 }
212
213 *fd_p = fd;
214 return fd;
215}
216*/
217
218
219uint32_t stat_diff ( stat64_t *a, stat64_t *b )
220{
221 uint32_t difference;
222#ifdef PARANOID
223 critical_on ( a == NULL );
224 critical_on ( b == NULL );
225#endif
226 difference = 0x0000;
227#define STAT_COMPARE(bit, field) \
228 if (a->field != b->field) \
229 difference |= bit;
230 STAT_COMPARE ( STAT_FIELD_DEV, st_dev );
231 STAT_COMPARE ( STAT_FIELD_INO, st_ino );
232 STAT_COMPARE ( STAT_FIELD_MODE, st_mode );
233 STAT_COMPARE ( STAT_FIELD_NLINK, st_nlink );
234 STAT_COMPARE ( STAT_FIELD_UID, st_uid );
235 STAT_COMPARE ( STAT_FIELD_GID, st_gid );
236 STAT_COMPARE ( STAT_FIELD_RDEV, st_rdev );
237 STAT_COMPARE ( STAT_FIELD_SIZE, st_size );
238 STAT_COMPARE ( STAT_FIELD_BLKSIZE, st_blksize );
239 STAT_COMPARE ( STAT_FIELD_BLOCKS, st_blocks );
240 STAT_COMPARE ( STAT_FIELD_ATIME, st_atime );
241 STAT_COMPARE ( STAT_FIELD_MTIME, st_mtime );
242 STAT_COMPARE ( STAT_FIELD_CTIME, st_ctime );
243#undef STAT_COMPARE
244 return difference;
245}
246
#define BUFSIZ
@ STAT_FIELD_RDEV
Definition ctx.h:297
@ STAT_FIELD_ATIME
Definition ctx.h:301
@ STAT_FIELD_INO
Definition ctx.h:292
@ STAT_FIELD_CTIME
Definition ctx.h:303
@ STAT_FIELD_BLOCKS
Definition ctx.h:300
@ STAT_FIELD_NLINK
Definition ctx.h:294
@ STAT_FIELD_SIZE
Definition ctx.h:298
@ STAT_FIELD_MTIME
Definition ctx.h:302
@ STAT_FIELD_GID
Definition ctx.h:296
@ STAT_FIELD_UID
Definition ctx.h:295
@ STAT_FIELD_MODE
Definition ctx.h:293
@ STAT_FIELD_DEV
Definition ctx.h:291
@ STAT_FIELD_BLKSIZE
Definition ctx.h:299
#define critical(...)
Definition error.h:32
#define error(...)
Definition error.h:36
#define debug(debug_level,...)
Definition error.h:50
#define critical_on(cond)
Definition error.h:33
int mkdirat_open(const char *const dir_path, int dirfd_parent, mode_t dir_mode)
Combination of mkdirat() and openat()
Definition fileutils.c:179
char * fd2fpath_malloc(int fd)
Definition fileutils.c:26
int fileutils_copy(const char *path_from, const char *path_to)
Copies file.
Definition fileutils.c:78
short int fileutils_calcdirlevel(const char *path)
Calculates directory level of a canonized path (actually it just counts "/"-s)
Definition fileutils.c:138
uint32_t stat_diff(stat64_t *a, stat64_t *b)
Definition fileutils.c:219
#define STAT_COMPARE(bit, field)
struct stat64 stat64_t
Definition port-hacks.h:65