Added SILC Thread Queue API
[silc.git] / lib / silcutil / silcfileutil.c
1 /*
2
3   silcfileutil.c
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 1997 - 2007 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19 /* $Id$ */
20
21 #include "silc.h"
22
23 /* Opens a file indicated by the filename `filename' with flags indicated
24    by the `flags'. */
25
26 int silc_file_open(const char *filename, int flags)
27 {
28   return silc_file_open_mode(filename, flags, 0600);
29 }
30
31 /* Opens a file indicated by the filename `filename' with flags indicated
32    by the `flags', and with the specified `mode'. */
33
34 int silc_file_open_mode(const char *filename, int flags, int mode)
35 {
36   int fd = open(filename, flags, mode);
37   if (fd < 0)
38     silc_set_errno_posix(errno);
39   return fd;
40 }
41
42 /* Reads data from file descriptor `fd' to `buf'. */
43
44 int silc_file_read(int fd, unsigned char *buf, SilcUInt32 buf_len)
45 {
46   int ret = read(fd, (void *)buf, buf_len);
47   if (ret < 0)
48     silc_set_errno_posix(errno);
49   return ret;
50 }
51
52 /* Writes `buffer' of length of `len' to file descriptor `fd'. */
53
54 int silc_file_write(int fd, const char *buffer, SilcUInt32 len)
55 {
56   int ret = write(fd, (const void *)buffer, len);
57   if (ret < 0)
58     silc_set_errno_posix(errno);
59   return ret;
60 }
61
62 /* Closes file descriptor */
63
64 int silc_file_close(int fd)
65 {
66   int ret = close(fd);
67   if (ret < 0)
68     silc_set_errno_posix(errno);
69   return ret;
70 }
71
72 /* Writes a buffer to the file. */
73
74 int silc_file_writefile(const char *filename, const char *buffer,
75                         SilcUInt32 len)
76 {
77   int fd;
78   int flags = O_CREAT | O_WRONLY | O_TRUNC;
79
80 #if defined(O_BINARY)
81   flags |= O_BINARY;
82 #endif /* O_BINARY */
83
84   if ((fd = open(filename, flags, 0644)) == -1) {
85     SILC_LOG_ERROR(("Cannot open file %s for writing: %s", filename,
86                     silc_errno_string(silc_errno)));
87     return -1;
88   }
89
90   if (silc_file_write(fd, buffer, len) == -1) {
91     SILC_LOG_ERROR(("Cannot write to file %s: %s", filename,
92                     silc_errno_string(silc_errno)));
93     silc_file_close(fd);
94     return -1;
95   }
96
97 #ifdef SILC_UNIX
98   fsync(fd);
99 #endif /* SILC_UNIX */
100
101   return silc_file_close(fd);
102 }
103
104 /* Writes a buffer to the file.  If the file is created specific mode is
105    set to the file. */
106
107 int silc_file_writefile_mode(const char *filename, const char *buffer,
108                              SilcUInt32 len, int mode)
109 {
110   int fd;
111   int flags = O_CREAT | O_WRONLY | O_TRUNC;
112
113 #if defined(O_BINARY)
114   flags |= O_BINARY;
115 #endif /* O_BINARY */
116
117   if ((fd = open(filename, flags, mode)) == -1) {
118     SILC_LOG_ERROR(("Cannot open file %s for writing: %s", filename,
119                     silc_errno_string(silc_errno)));
120     return -1;
121   }
122
123   if ((silc_file_write(fd, buffer, len)) == -1) {
124     SILC_LOG_ERROR(("Cannot write to file %s: %s", filename,
125                     silc_errno_string(silc_errno)));
126     silc_file_close(fd);
127     return -1;
128   }
129
130 #ifdef SILC_UNIX
131   fsync(fd);
132 #endif /* SILC_UNIX */
133
134   return silc_file_close(fd);
135 }
136
137 /* Reads a file to a buffer. The allocated buffer is returned. Length of
138    the file read is returned to the return_len argument. */
139
140 char *silc_file_readfile(const char *filename, SilcUInt32 *return_len,
141                          SilcStack stack)
142 {
143   int fd;
144   unsigned char *buffer;
145   int filelen;
146
147   fd = silc_file_open(filename, O_RDONLY);
148   if (fd < 0) {
149     if (silc_errno == SILC_ERR_NO_SUCH_FILE)
150       return NULL;
151     SILC_LOG_ERROR(("Cannot open file %s: %s", filename,
152                     silc_errno_string(silc_errno)));
153     return NULL;
154   }
155
156   filelen = lseek(fd, (off_t)0L, SEEK_END);
157   if (filelen < 0) {
158     silc_set_errno_posix(errno);
159     silc_file_close(fd);
160     return NULL;
161   }
162   if (lseek(fd, (off_t)0L, SEEK_SET) < 0) {
163     silc_set_errno_posix(errno);
164     silc_file_close(fd);
165     return NULL;
166   }
167
168   buffer = silc_calloc(filelen + 1, sizeof(*buffer));
169
170   if ((silc_file_read(fd, buffer, filelen)) == -1) {
171     memset(buffer, 0, sizeof(buffer));
172     silc_file_close(fd);
173     SILC_LOG_ERROR(("Cannot read from file %s: %s", filename,
174                     silc_errno_string(silc_errno)));
175     return NULL;
176   }
177
178   silc_file_close(fd);
179   buffer[filelen] = EOF;
180
181   if (return_len)
182     *return_len = filelen;
183
184   return (char *)buffer;
185 }
186
187 /* Returns the size of `filename'. Returns 0 on error. */
188
189 SilcUInt64 silc_file_size(const char *filename)
190 {
191   int ret;
192   struct stat stats;
193
194 #ifdef SILC_WIN32
195   ret = stat(filename, &stats);
196 #endif /* SILC_WIN32 */
197 #ifdef SILC_UNIX
198   ret = lstat(filename, &stats);
199 #endif /* SILC_UNIX */
200 #ifdef SILC_SYMBIAN
201   ret = stat(filename, &stats);
202 #endif /* SILC_SYMBIAN */
203   if (ret < 0) {
204     silc_set_errno_posix(errno);
205     return 0;
206   }
207
208   return (SilcUInt64)stats.st_size;
209 }