1766813a68178e69024241111305552412de1aae
[oweals/gnunet.git] / src / hello / gnunet-hello.c
1 /*
2      This file is part of GNUnet
3      Copyright (C) 2012 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      Affero General Public License for more details.
14     
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18 /**
19  * @file hello/gnunet-hello.c
20  * @brief change HELLO files to never expire
21  * @author Christian Grothoff
22  */
23 #include "platform.h"
24 #include "gnunet_protocols.h"
25 #include "gnunet_hello_lib.h"
26
27 /**
28  * Closure for #add_to_buf().
29  */
30 struct AddContext
31 {
32   /**
33    * Where to add.
34    */
35   char *buf;
36
37   /**
38    * Maximum number of bytes left
39    */
40   size_t max;
41
42   /**
43    * Number of bytes added so far.
44    */
45   size_t ret;
46 };
47
48 static int address_count;
49
50
51 /**
52  * Add the given address with infinit expiration to the buffer.
53  *
54  * @param cls closure
55  * @param address address to add
56  * @param expiration old expiration
57  * @return #GNUNET_OK keep iterating
58  */
59 static int
60 add_to_buf (void *cls,
61             const struct GNUNET_HELLO_Address *address,
62             struct GNUNET_TIME_Absolute expiration)
63 {
64   struct AddContext *ac = cls;
65   size_t ret;
66
67   ret = GNUNET_HELLO_add_address (address,
68                                   GNUNET_TIME_UNIT_FOREVER_ABS,
69                                   ac->buf,
70                                   ac->max);
71   ac->buf += ret;
72   ac->max -= ret;
73   ac->ret += ret;
74   address_count ++;
75   return GNUNET_OK;
76 }
77
78
79 /**
80  * Add addresses from the address list to the HELLO.
81  *
82  * @param cls the HELLO with the addresses to add
83  * @param max maximum space available
84  * @param buf where to add the addresses
85  * @return number of bytes added, 0 to terminate
86  */
87 static ssize_t
88 add_from_hello (void *cls,
89                 size_t max,
90                 void *buf)
91 {
92   struct GNUNET_HELLO_Message **orig = cls;
93   struct AddContext ac;
94
95   if (NULL == *orig)
96     return GNUNET_SYSERR; /* already done */
97   ac.buf = buf;
98   ac.max = max;
99   ac.ret = 0;
100   GNUNET_assert (NULL ==
101                  GNUNET_HELLO_iterate_addresses (*orig,
102                                                  GNUNET_NO, &add_to_buf,
103                                                  &ac));
104   *orig = NULL;
105   return ac.ret;
106 }
107
108
109 int
110 main (int argc, char *argv[])
111 {
112   struct GNUNET_DISK_FileHandle *fh;
113   struct GNUNET_HELLO_Message *orig;
114   struct GNUNET_HELLO_Message *result;
115   struct GNUNET_PeerIdentity pid;
116   uint64_t fsize;
117   address_count = 0;
118
119   GNUNET_log_setup ("gnunet-hello", "INFO", NULL);
120   if (argc != 2)
121   {
122     FPRINTF (stderr,
123              "%s",
124              _("Call with name of HELLO file to modify.\n"));
125     return 1;
126   }
127   if (GNUNET_OK != GNUNET_DISK_file_size (argv[1], &fsize, GNUNET_YES, GNUNET_YES))
128   {
129     FPRINTF (stderr,
130              _("Error accessing file `%s': %s\n"),
131              argv[1],
132              STRERROR (errno));
133     return 1;
134   }
135   if (fsize > 65536)
136   {
137     FPRINTF (stderr,
138              _("File `%s' is too big to be a HELLO\n"),
139              argv[1]);
140     return 1;
141   }
142   if (fsize < sizeof (struct GNUNET_MessageHeader))
143   {
144     FPRINTF (stderr,
145              _("File `%s' is too small to be a HELLO\n"),
146              argv[1]);
147     return 1;
148   }
149   fh = GNUNET_DISK_file_open (argv[1],
150                               GNUNET_DISK_OPEN_READ,
151                               GNUNET_DISK_PERM_USER_READ);
152   if (NULL == fh)
153   {
154     FPRINTF (stderr,
155              _("Error opening file `%s': %s\n"),
156              argv[1],
157              STRERROR (errno));
158     return 1;
159   }
160   {
161     char buf[fsize] GNUNET_ALIGN;
162
163     GNUNET_assert (fsize ==
164                    GNUNET_DISK_file_read (fh, buf, fsize));
165     GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
166     orig = (struct GNUNET_HELLO_Message *) buf;
167     if ( (fsize < GNUNET_HELLO_size (orig)) ||
168          (GNUNET_OK != GNUNET_HELLO_get_id (orig,
169                                             &pid)) )
170     {
171       FPRINTF (stderr,
172                _("Did not find well-formed HELLO in file `%s'\n"),
173                argv[1]);
174       return 1;
175     }
176     {
177       char *pids;
178
179       pids = GNUNET_CRYPTO_eddsa_public_key_to_string (&pid.public_key);
180       fprintf (stdout,
181                "Processing HELLO for peer `%s'\n",
182                pids);
183       GNUNET_free (pids);
184     }
185     result = GNUNET_HELLO_create (&pid.public_key,
186                                   &add_from_hello,
187                                   &orig,
188                                   GNUNET_HELLO_is_friend_only (orig));
189     GNUNET_assert (NULL != result);
190      fh = GNUNET_DISK_file_open (argv[1],
191                                  GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_TRUNCATE,
192                                  GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
193      if (NULL == fh)
194      {
195        FPRINTF (stderr,
196                 _("Error opening file `%s': %s\n"),
197                 argv[1],
198                 STRERROR (errno));
199        GNUNET_free (result);
200        return 1;
201      }
202      fsize = GNUNET_HELLO_size (result);
203      if (fsize != GNUNET_DISK_file_write (fh,
204                                           result,
205                                           fsize))
206      {
207        FPRINTF (stderr,
208                 _("Error writing HELLO to file `%s': %s\n"),
209                 argv[1],
210                 STRERROR (errno));
211        (void) GNUNET_DISK_file_close (fh);
212        return 1;
213      }
214     GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fh));
215   }
216   FPRINTF (stderr,
217            _("Modified %u addresses, wrote %u bytes\n"),
218            address_count,
219            (unsigned int) fsize);
220   return 0;
221 }
222
223 /* end of gnunet-hello.c */