clsync
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 
26 char *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 
78 int 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 
138 short 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  */
179 int 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  * /
206 int 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 
219 uint32_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 
STAT_FIELD_NLINK
@ STAT_FIELD_NLINK
Definition: ctx.h:294
mkdirat_open
int mkdirat_open(const char *const dir_path, int dirfd_parent, mode_t dir_mode)
Combination of mkdirat() and openat()
Definition: fileutils.c:179
STAT_FIELD_MTIME
@ STAT_FIELD_MTIME
Definition: ctx.h:302
STAT_FIELD_CTIME
@ STAT_FIELD_CTIME
Definition: ctx.h:303
STAT_FIELD_BLKSIZE
@ STAT_FIELD_BLKSIZE
Definition: ctx.h:299
STAT_FIELD_UID
@ STAT_FIELD_UID
Definition: ctx.h:295
stat_diff
uint32_t stat_diff(stat64_t *a, stat64_t *b)
Definition: fileutils.c:219
STAT_FIELD_ATIME
@ STAT_FIELD_ATIME
Definition: ctx.h:301
STAT_FIELD_DEV
@ STAT_FIELD_DEV
Definition: ctx.h:291
error
#define error(...)
Definition: error.h:36
error.h
fd2fpath_malloc
char * fd2fpath_malloc(int fd)
Definition: fileutils.c:26
STAT_FIELD_INO
@ STAT_FIELD_INO
Definition: ctx.h:292
malloc.h
debug
#define debug(debug_level,...)
Definition: error.h:50
STAT_FIELD_SIZE
@ STAT_FIELD_SIZE
Definition: ctx.h:298
critical
#define critical(...)
Definition: error.h:32
BUFSIZ
#define BUFSIZ
Definition: configuration.h:6
common.h
STAT_FIELD_BLOCKS
@ STAT_FIELD_BLOCKS
Definition: ctx.h:300
STAT_FIELD_RDEV
@ STAT_FIELD_RDEV
Definition: ctx.h:297
stat64_t
struct stat64 stat64_t
Definition: port-hacks.h:65
fileutils_copy
int fileutils_copy(const char *path_from, const char *path_to)
Copies file.
Definition: fileutils.c:78
fileutils_calcdirlevel
short int fileutils_calcdirlevel(const char *path)
Calculates directory level of a canonized path (actually it just counts "/"-s)
Definition: fileutils.c:138
critical_on
#define critical_on(cond)
Definition: error.h:33
STAT_COMPARE
#define STAT_COMPARE(bit, field)
STAT_FIELD_GID
@ STAT_FIELD_GID
Definition: ctx.h:296
STAT_FIELD_MODE
@ STAT_FIELD_MODE
Definition: ctx.h:293