source: trunk/libtransmission/file-posix.c @ 14314

Last change on this file since 14314 was 14314, checked in by jordan, 8 years ago

(trunk, libT) mike.dld's 4160-02a-path.patch: portability wrapper around file paths.

File size: 4.4 KB
Line 
1/*
2 * This file Copyright (C) 2013-2014 Mnemosyne LLC
3 *
4 * It may be used under the GNU GPL versions 2 or 3
5 * or any future license endorsed by Mnemosyne LLC.
6 *
7 * $Id$
8 */
9
10#if defined (HAVE_CANONICALIZE_FILE_NAME) && !defined (_GNU_SOURCE)
11 #define _GNU_SOURCE
12#endif
13
14#include <assert.h>
15#include <errno.h>
16#include <libgen.h> /* basename (), dirname () */
17#include <limits.h> /* PATH_MAX */
18#include <stdio.h>
19#include <stdlib.h>
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <unistd.h>
23
24#include "transmission.h"
25#include "file.h"
26#include "utils.h"
27
28#ifndef PATH_MAX
29 #define PATH_MAX 4096
30#endif
31
32static void
33set_system_error (tr_error ** error,
34                  int         code)
35{
36  if (error == NULL)
37    return;
38
39  tr_error_set_literal (error, code, tr_strerror (code));
40}
41
42static void
43set_system_error_if_file_found (tr_error ** error,
44                                int         code)
45{
46  if (code != ENOENT)
47    set_system_error (error, code);
48}
49
50static void
51stat_to_sys_path_info (const struct stat * sb,
52                       tr_sys_path_info  * info)
53{
54  if (S_ISREG (sb->st_mode))
55    info->type = TR_SYS_PATH_IS_FILE;
56  else if (S_ISDIR (sb->st_mode))
57    info->type = TR_SYS_PATH_IS_DIRECTORY;
58  else
59    info->type = TR_SYS_PATH_IS_OTHER;
60
61  info->size = (uint64_t) sb->st_size;
62  info->last_modified_at = sb->st_mtime;
63}
64
65bool
66tr_sys_path_exists (const char  * path,
67                    tr_error   ** error)
68{
69  bool ret;
70
71  assert (path != NULL);
72
73  ret = access (path, F_OK) != -1;
74
75  if (!ret)
76    set_system_error_if_file_found (error, errno);
77
78  return ret;
79}
80
81bool
82tr_sys_path_get_info (const char        * path,
83                      int                 flags,
84                      tr_sys_path_info  * info,
85                      tr_error         ** error)
86{
87  bool ret;
88  struct stat sb;
89
90  assert (path != NULL);
91  assert (info != NULL);
92
93  if ((flags & TR_SYS_PATH_NO_FOLLOW) == 0)
94    ret = stat (path, &sb) != -1;
95  else
96    ret = lstat (path, &sb) != -1;
97
98  if (ret)
99    stat_to_sys_path_info (&sb, info);
100  else
101    set_system_error (error, errno);
102
103  return ret;
104}
105
106bool
107tr_sys_path_is_same (const char  * path1,
108                     const char  * path2,
109                     tr_error   ** error)
110{
111  bool ret = false;
112  struct stat sb1, sb2;
113
114  assert (path1 != NULL);
115  assert (path2 != NULL);
116
117  if (stat (path1, &sb1) != -1 && stat (path2, &sb2) != -1)
118    ret = sb1.st_dev == sb2.st_dev && sb1.st_ino == sb2.st_ino;
119  else
120    set_system_error_if_file_found (error, errno);
121
122  return ret;
123}
124
125char *
126tr_sys_path_resolve (const char  * path,
127                     tr_error   ** error)
128{
129  char * ret = NULL;
130  char * tmp = NULL;
131
132  assert (path != NULL);
133
134#if defined (HAVE_CANONICALIZE_FILE_NAME)
135
136  ret = canonicalize_file_name (path);
137
138#endif
139
140#if defined (_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200809L
141
142  /* Better safe than sorry: realpath () officially supports NULL as destination
143     starting off POSIX.1-2008. */
144
145  if (ret == NULL)
146    ret = realpath (path, NULL);
147
148#endif
149
150  if (ret == NULL)
151    {
152      tmp = tr_new (char, PATH_MAX);
153      ret = realpath (path, tmp);
154      if (ret != NULL)
155        ret = tr_strdup (ret);
156    }
157
158  if (ret == NULL)
159    set_system_error (error, errno);
160
161  tr_free (tmp);
162
163  return ret;
164}
165
166char *
167tr_sys_path_basename (const char  * path,
168                      tr_error   ** error)
169{
170  char * ret = NULL;
171  char * tmp;
172
173  assert (path != NULL);
174
175  tmp = tr_strdup (path);
176  ret = basename (tmp);
177  if (ret != NULL)
178    ret = tr_strdup (ret);
179  else
180    set_system_error (error, errno);
181
182  tr_free (tmp);
183
184  return ret;
185}
186
187char *
188tr_sys_path_dirname (const char  * path,
189                     tr_error   ** error)
190{
191  char * ret = NULL;
192  char * tmp;
193
194  assert (path != NULL);
195
196  tmp = tr_strdup (path);
197  ret = dirname (tmp);
198  if (ret != NULL)
199    ret = tr_strdup (ret);
200  else
201    set_system_error (error, errno);
202
203  tr_free (tmp);
204
205  return ret;
206}
207
208bool
209tr_sys_path_rename (const char  * src_path,
210                    const char  * dst_path,
211                    tr_error   ** error)
212{
213  bool ret;
214
215  assert (src_path != NULL);
216  assert (dst_path != NULL);
217
218  ret = rename (src_path, dst_path) != -1;
219
220  if (!ret)
221    set_system_error (error, errno);
222
223  return ret;
224}
225
226bool
227tr_sys_path_remove (const char  * path,
228                    tr_error   ** error)
229{
230  bool ret;
231
232  assert (path != NULL);
233
234  ret = remove (path) != -1;
235
236  if (!ret)
237    set_system_error (error, errno);
238
239  return ret;
240}
Note: See TracBrowser for help on using the repository browser.