~ubuntu-branches/ubuntu/utopic/binkd/utopic-proposed

« back to all changes in this revision

Viewing changes to inbound.c

  • Committer: Bazaar Package Importer
  • Author(s): Marco d'Itri
  • Date: 2002-03-24 22:52:25 UTC
  • Revision ID: james.westby@ubuntu.com-20020324225225-7ru6itlapn03nl35
Tags: upstream-0.9.5a
ImportĀ upstreamĀ versionĀ 0.9.5a

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  inbound.c -- inbound handling
 
3
 *
 
4
 *  inbound.c is a part of binkd project
 
5
 *
 
6
 *  Copyright (C) 1996-1997  Dima Maloff, 5047/13
 
7
 *
 
8
 *  This program is free software; you can redistribute it and/or modify
 
9
 *  it under the terms of the GNU General Public License as published by
 
10
 *  the Free Software Foundation; either version 2 of the License, or
 
11
 *  (at your option) any later version. See COPYING.
 
12
 */
 
13
 
 
14
/*
 
15
 * $Id: inbound.c,v 2.1 2001/04/23 07:58:57 gul Exp $
 
16
 *
 
17
 * $Log: inbound.c,v $
 
18
 * Revision 2.1  2001/04/23 07:58:57  gul
 
19
 * getfree() on large drives fixed
 
20
 *
 
21
 * Revision 2.0  2001/01/10 12:12:38  gul
 
22
 * Binkd is under CVS again
 
23
 *
 
24
 * Revision 1.10  1997/10/23  04:03:07  mff
 
25
 * minor fixes
 
26
 *
 
27
 * Revision 1.9  1997/05/17  08:42:35  mff
 
28
 * Added realname param to inb_test()
 
29
 *
 
30
 * Revision 1.8  1997/03/15  05:08:17  mff
 
31
 * utime() replaced with touch()
 
32
 *
 
33
 * Revision 1.7  1997/03/09  07:19:37  mff
 
34
 * Fixed bugs with `#' in filenames and incorrect killing of
 
35
 * partial packets
 
36
 *
 
37
 * Revision 1.6  1997/02/13  07:08:39  mff
 
38
 * Support for fileboxes
 
39
 *
 
40
 * Revision 1.5  1997/02/07  07:03:16  mff
 
41
 * Added more paranoia
 
42
 */
 
43
 
 
44
#include <stdio.h>
 
45
#include <stdlib.h>
 
46
#include <errno.h>
 
47
#include <string.h>
 
48
#include <ctype.h>
 
49
#include <sys/types.h>
 
50
#include <sys/stat.h>
 
51
#include <time.h>
 
52
 
 
53
#include "Config.h"
 
54
#include "sys.h"
 
55
#include "readcfg.h"
 
56
#include "inbound.h"
 
57
#include "tools.h"
 
58
#include "protocol.h"
 
59
#include "readdir.h"
 
60
 
 
61
/* Removes both xxxxx.hr and it's xxxxx.dt */
 
62
static void remove_hr (char *path)
 
63
{
 
64
  int rc;
 
65
 
 
66
  strcpy (strrchr (path, '.'), ".dt");
 
67
  rc = delete (path);
 
68
  strcpy (strrchr (path, '.'), ".hr");
 
69
  if (rc == 0)
 
70
  {
 
71
    delete (path);
 
72
  }
 
73
}
 
74
 
 
75
static int creat_tmp_name (char *s, char *file, off_t size,
 
76
                            time_t time, FTN_ADDR *from, char *inbound)
 
77
{
 
78
  FILE *f;
 
79
  char tmp[20];
 
80
  char *t;
 
81
  char node[FTN_ADDR_SZ + 1];
 
82
 
 
83
  strnzcpy (s, inbound, MAXPATHLEN);
 
84
  strnzcat (s, PATH_SEPARATOR, MAXPATHLEN);
 
85
  t = s + strlen (s);
 
86
  while (1)
 
87
  {
 
88
    sprintf (tmp, "%08lx.hr", rnd ());
 
89
    strnzcat (s, tmp, MAXPATHLEN);
 
90
    if (create_empty_sem_file (s))
 
91
    {
 
92
      if ((f = fopen (s, "w")) == 0)
 
93
      {
 
94
        Log (1, "%s: %s", s, strerror (errno));
 
95
        return 0;
 
96
      }
 
97
      ftnaddress_to_str (node, from);
 
98
      fprintf (f, "%s %li %li %s\n",
 
99
               file, (long int) size, (long int) time, node);
 
100
      fclose (f);
 
101
      break;
 
102
    }
 
103
    *t = 0;
 
104
  }
 
105
  return 1;
 
106
}
 
107
 
 
108
static int to_be_deleted (char *tmp_name, char *netname)
 
109
{
 
110
  struct stat sb;
 
111
 
 
112
  strcpy (strrchr (tmp_name, '.'), ".dt");
 
113
  if (stat (tmp_name, &sb) == 0 && kill_old_partial_files != 0 &&
 
114
      time (0) - sb.st_mtime > kill_old_partial_files)
 
115
  {
 
116
    Log (4, "found old .dt/.hr files for %s", netname);
 
117
    return 1;
 
118
  }
 
119
  strcpy (strrchr (tmp_name, '.'), ".hr");
 
120
  return 0;
 
121
}
 
122
 
 
123
/*
 
124
 * Searches for the ``file'' in the inbound and returns it's tmp name in s.
 
125
 * S must have MAXPATHLEN chars. Returns 0 on error, 1=found, 2=created.
 
126
 */
 
127
int find_tmp_name (char *s, char *file, off_t size,
 
128
                    time_t time, FTN_ADDR *from, int nfa, char *inbound)
 
129
{
 
130
  char buf[MAXPATHLEN + 80];
 
131
  DIR *dp;
 
132
  struct dirent *de;
 
133
  FILE *f;
 
134
  int i, found = 0;
 
135
  char *t;
 
136
 
 
137
  if (temp_inbound[0])
 
138
    inbound = temp_inbound;
 
139
 
 
140
  if ((dp = opendir (inbound)) == 0)
 
141
  {
 
142
    Log (1, "cannot opendir %s: %s", inbound, strerror (errno));
 
143
    return 0;
 
144
  }
 
145
 
 
146
  strnzcpy (s, inbound, MAXPATHLEN);
 
147
  strnzcat (s, PATH_SEPARATOR, MAXPATHLEN);
 
148
  t = s + strlen (s);
 
149
  while ((de = readdir (dp)) != 0)
 
150
  {
 
151
    for (i = 0; i < 8; ++i)
 
152
      if (!isxdigit (de->d_name[i]))
 
153
        break;
 
154
    if (i < 8 || STRICMP (de->d_name + 8, ".hr"))
 
155
      continue;
 
156
    strnzcat (s, de->d_name, MAXPATHLEN);
 
157
    if ((f = fopen (s, "r")) == 0 || !fgets (buf, sizeof (buf), f))
 
158
    {
 
159
      Log (1, "find_tmp_name: %s: %s", de->d_name, strerror (errno));
 
160
      if (f)
 
161
        fclose (f);
 
162
    }
 
163
    else
 
164
    {
 
165
      char *w[4];
 
166
      FTN_ADDR fa;
 
167
 
 
168
      fclose (f);
 
169
      FA_ZERO (&fa);
 
170
      for (i = 0; i < 4; ++i)
 
171
        w[i] = getwordx (buf, i + 1, GWX_NOESC);
 
172
 
 
173
      if (!strcmp (w[0], file) && parse_ftnaddress (w[3], &fa))
 
174
      {
 
175
        for (i = 0; i < nfa; i++)
 
176
          if (!ftnaddress_cmp (&fa, from + i))
 
177
            break;
 
178
        if (size == (off_t) atol (w[1]) &&
 
179
            (time & ~1) == (atol (w[2]) & ~1) &&
 
180
            i < nfa)
 
181
        {
 
182
          found = 1;
 
183
        }
 
184
        else if (kill_dup_partial_files && i < nfa)
 
185
        {
 
186
          Log (4, "dup partial file (%s):", w[0]);
 
187
          remove_hr (s);
 
188
        }
 
189
      }
 
190
      else if (to_be_deleted (s, w[0]))
 
191
      {
 
192
        remove_hr (s);
 
193
      }
 
194
 
 
195
      for (i = 0; i < 4; ++i)
 
196
        if (w[i])
 
197
          free (w[i]);
 
198
    }
 
199
    if (found)
 
200
      break;
 
201
    else
 
202
      *t = 0;
 
203
  }
 
204
  closedir (dp);
 
205
 
 
206
  /* New file */
 
207
  if (!found)
 
208
  {
 
209
    Log (5, "file not found, trying to create a tmpname");
 
210
    if (creat_tmp_name (s, file, size, time, from, inbound))
 
211
      found = 2;
 
212
    else
 
213
      return 0;
 
214
  }
 
215
 
 
216
  /* Replacing .hr with .dt */
 
217
  strcpy (strrchr (s, '.'), ".dt");
 
218
  return found;
 
219
}
 
220
 
 
221
FILE *inb_fopen (char *netname, off_t size,
 
222
                  time_t time, FTN_ADDR *from, int nfa, char *inbound)
 
223
{
 
224
  char buf[MAXPATHLEN + 1];
 
225
  struct stat sb;
 
226
  FILE *f;
 
227
 
 
228
  if (!find_tmp_name (buf, netname, size, time, from, nfa, inbound))
 
229
    return 0;
 
230
 
 
231
  if ((f = fopen (buf, "ab")) == 0)
 
232
    Log (1, "%s: %s", buf, strerror (errno));
 
233
  fseek (f, 0, SEEK_END);              /* Work-around MSVC bug */
 
234
 
 
235
#if defined(OS2)
 
236
  DosSetFHState(fileno(f), OPEN_FLAGS_NOINHERIT);
 
237
#elif defined(EMX)
 
238
  fcntl(fileno(f), F_SETFD, FD_CLOEXEC);
 
239
#endif
 
240
 
 
241
  /* Checking for free space */
 
242
  if (fstat (fileno (f), &sb) == 0)
 
243
  {
 
244
    /* Free space req-d (Kbytes) */
 
245
    int req_free = (strcmp (inbound, inbound_nonsecure) ?
 
246
                    minfree : minfree_nonsecure);
 
247
 
 
248
    if (req_free >= 0 &&
 
249
        getfree (inbound) < (unsigned long)((size - sb.st_size + 1023) / 1024 + req_free))
 
250
    {
 
251
      Log (1, "no enough free space in %s (%liK, req-d %liK)",
 
252
           inbound,
 
253
           (long) getfree (inbound),
 
254
           (long) (size - sb.st_size + 1023) / 1024 + req_free);
 
255
      fclose (f);
 
256
      return 0;
 
257
    }
 
258
  }
 
259
  else
 
260
    Log (1, "%s: fstat: %s", netname, strerror (errno));
 
261
 
 
262
  return f;
 
263
}
 
264
 
 
265
int inb_reject (char *netname, off_t size,
 
266
                 time_t time, FTN_ADDR *from, int nfa, char *inbound)
 
267
{
 
268
  char tmp_name[MAXPATHLEN + 1];
 
269
 
 
270
  if (find_tmp_name (tmp_name, netname, size, time, from, nfa, inbound) != 1)
 
271
  {
 
272
    Log (1, "missing tmp file for %s!", netname);
 
273
    return 0;
 
274
  }
 
275
  else
 
276
  {
 
277
    Log (2, "rejecting %s", netname);
 
278
    /* Replacing .dt with .hr and removing temp. file */
 
279
    strcpy (strrchr (tmp_name, '.'), ".hr");
 
280
    remove_hr (tmp_name);
 
281
    return 1;
 
282
  }
 
283
}
 
284
 
 
285
/*
 
286
 * File is complete, rename it to it's realname. 1=ok, 0=failed.
 
287
 * Sets realname[MAXPATHLEN]
 
288
 */
 
289
int inb_done (char *netname, off_t size, time_t time,
 
290
              FTN_ADDR *from, int nfa, char *inbound, char *real_name)
 
291
{
 
292
  char tmp_name[MAXPATHLEN + 1];
 
293
  char *s, *u;
 
294
 
 
295
  *real_name = 0;
 
296
 
 
297
  if (find_tmp_name (tmp_name, netname, size, time, from, nfa, inbound) != 1)
 
298
  {
 
299
    Log (1, "missing tmp file for %s!", netname);
 
300
    return 0;
 
301
  }
 
302
 
 
303
  strnzcpy (real_name, inbound, MAXPATHLEN);
 
304
  strnzcat (real_name, PATH_SEPARATOR, MAXPATHLEN);
 
305
  s = real_name + strlen (real_name);
 
306
  strnzcat (real_name, u = strdequote (netname), MAXPATHLEN);
 
307
  free (u);
 
308
  strwipe (s);
 
309
  s = real_name + strlen (real_name) - 1;
 
310
 
 
311
  /* gul: for *.pkt and *.?ic (tic, zic etc.) change name but not extension */
 
312
  /* ditto for arcmail -- mff */
 
313
  if (ispkt (netname) || istic (netname) || isarcmail (netname))
 
314
    s -= 4;
 
315
 
 
316
  if (touch (tmp_name, time) != 0)
 
317
    Log (1, "touch %s: %s", tmp_name, strerror (errno));
 
318
 
 
319
  while (1)
 
320
  {
 
321
    if (!RENAME (tmp_name, real_name))
 
322
    {
 
323
      Log (2, "%s -> %s", netname, real_name);
 
324
      break;
 
325
    }
 
326
    else
 
327
    {
 
328
      if (errno != EEXIST && errno != EACCES && errno != EAGAIN)
 
329
      {
 
330
        Log (1, "cannot rename %s to it's realname: %s! (data stored in %s)",
 
331
             netname, strerror (errno), tmp_name);
 
332
        *real_name = 0;
 
333
        return 0;
 
334
      }
 
335
      Log (2, "error renaming `%s' to `%s': %s",
 
336
           netname, real_name, strerror (errno));
 
337
    }
 
338
 
 
339
    if (isalpha (*s) && toupper (*s) != 'Z')
 
340
      ++*s;
 
341
    else if (isdigit (*s) && toupper (*s) != '9')
 
342
      ++*s;
 
343
    else if (*s == '9')
 
344
      *s = 'a';
 
345
    else if (*--s == '.' || *s == '\\' || *s == '/')
 
346
    {
 
347
      Log (1, "cannot rename %s to it's realname! (data stored in %s)",
 
348
           netname, tmp_name);
 
349
      *real_name = 0;
 
350
      return 0;
 
351
    }
 
352
  }
 
353
 
 
354
  /* Replacing .dt with .hr and removing temp. file */
 
355
  strcpy (strrchr (tmp_name, '.'), ".hr");
 
356
  delete (tmp_name);
 
357
  return 1;
 
358
}
 
359
 
 
360
/*
 
361
 * Checks if the file already exists in our inbound. !0=ok, 0=failed.
 
362
 * Sets realname[MAXPATHLEN]
 
363
 */
 
364
int inb_test (char *filename, off_t size, time_t t,
 
365
               char *inbound, char fp[])
 
366
{
 
367
  char *s, *u;
 
368
  struct stat sb;
 
369
 
 
370
  strnzcpy (fp, inbound, MAXPATHLEN);
 
371
  strnzcat (fp, PATH_SEPARATOR, MAXPATHLEN);
 
372
  s = fp + strlen (fp);
 
373
  strnzcat (fp, u = strdequote (filename), MAXPATHLEN);
 
374
  free (u);
 
375
  strwipe (s);
 
376
 
 
377
  return stat (fp, &sb) == 0 &&  sb.st_size == size &&
 
378
    (sb.st_mtime & ~1) == (t & ~1);
 
379
}