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