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