Merge branch 'topic/mm-fixes' of git://208.110.73.182/silc into silc.1.1.branch
[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 {
129   int fd;
130   char *buffer;
131   int filelen;
132
133   fd = silc_file_open(filename, O_RDONLY);
134   if (fd < 0) {
135     if (errno == ENOENT)
136       return NULL;
137     SILC_LOG_ERROR(("Cannot open file %s: %s", filename, strerror(errno)));
138     return NULL;
139   }
140
141   filelen = lseek(fd, (off_t)0L, SEEK_END);
142   if (filelen < 0) {
143     silc_file_close(fd);
144     return NULL;
145   }
146   if (lseek(fd, (off_t)0L, SEEK_SET) < 0) {
147     silc_file_close(fd);
148     return NULL;
149   }
150
151   if (filelen < 0) {
152     SILC_LOG_ERROR(("Cannot open file %s: %s", filename, strerror(errno)));
153     silc_file_close(fd);
154     return NULL;
155   }
156
157   buffer = silc_calloc(filelen + 1, sizeof(char));
158
159   if ((silc_file_read(fd, buffer, filelen)) == -1) {
160     memset(buffer, 0, sizeof(buffer));
161     silc_file_close(fd);
162     SILC_LOG_ERROR(("Cannot read from file %s: %s", filename,
163                     strerror(errno)));
164     return NULL;
165   }
166
167   silc_file_close(fd);
168   buffer[filelen] = EOF;
169
170   if (return_len)
171     *return_len = filelen;
172
173   return buffer;
174 }
175
176 /* Returns the size of `filename'. Returns 0 on error. */
177
178 SilcUInt64 silc_file_size(const char *filename)
179 {
180   int ret;
181   struct stat stats;
182
183 #ifdef SILC_WIN32
184   ret = stat(filename, &stats);
185 #endif /* SILC_WIN32 */
186 #ifdef SILC_UNIX
187   ret = lstat(filename, &stats);
188 #endif /* SILC_UNIX */
189 #ifdef SILC_SYMBIAN
190   ret = stat(filename, &stats);
191 #endif /* SILC_SYMBIAN */
192   if (ret < 0)
193     return 0;
194
195   return (SilcUInt64)stats.st_size;
196 }