aboutsummaryrefslogtreecommitdiff
path: root/src/wydawca.h
blob: 2de86f0488451c27a861d663e29f0cc7f54d9310 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
/* wydawca - FTP release synchronization daemon
   Copyright (C) 2007 Sergey Poznyakoff

   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 3 of the License, or (at your
   option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License along
   with this program. If not, see <http://www.gnu.org/licenses/>. */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <syslog.h>
#include <getopt.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <pwd.h>
#include <grp.h>
#include <signal.h>
#include <limits.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "error.h"
#include "xalloc.h"
#include "progname.h"
#include "backupfile.h"
#include "inttostr.h"
#include "gsc.h"

/* The range of directive versions we accept (major * 100 + minor) */
#define MIN_DIRECTIVE_VERSION 101
#define MAX_DIRECTIVE_VERSION 101

/* Default modes for mkdir and creat commands: rely on the umask value */
#define MKDIR_PERMISSIONS 0777
#define CREAT_PERMISSIONS 0666

#define NITEMS(a) (sizeof(a)/sizeof((a)[0]))

enum access_method_type
  {
    method_none,           /* Undefined or no method */
    method_sql,            /* Use SQL database */
    method_builtin,        /* Use built-in facilities */
    method_external        /* Invoke an external program */
  };

struct access_method
{
  enum access_method_type type;   /* Access method type */
  char *param[2];                 /* Parameters. The semantics differs
				     depending on type. For SQL:
				      0 - Identifier of the SQL struct
				          to use;
 				      1 - Request template */		
				     
  int init_passed;                /* Initialization count */
  char *result;                   /* Result storage */
  size_t result_size;             /* Size of result */
  unsigned ncol;                  /* Number of columns per row */
  unsigned nrow;                  /* Number of rows */
  union
  {
    struct sqlconn *sqlconn;      /* type == method_sql */
    /* More to come */
  } v;
};


/* Archive types */

enum archive_type
  {
    archive_none,         /* No archivation requested */
    archive_directory,    /* Archive by moving files to a separate directory
			     hierarchy */
    archive_tar           /* Archive by appending to a tar file (tar -r) */
  };

struct archive_descr
{
  enum archive_type type;        /* Archivation type */
  char *name;                    /* Directory name if type==archive_directory,
				    archive file name if type==archive_tar */
  enum backup_type backup_type;  /* Requested backup type if
				    type == archive_directory */
};



/* A source/destination directory pair. This structure contains all the
   data necessary for releasing files from source to destination */
struct directory_pair
{
  char *url;
  char *source_dir;                      /* Source directory */
  char *dest_dir;                        /* Destination directory */
  time_t file_sweep_time;                /* Remove invalid/unprocessed files
					    after this amount of time */
  struct access_method *verify_method;   /* Method for verification user's
					    access to the project */
  struct access_method *gpg_key_method;  /* Method for retrieving the user
					    public key */
  struct access_method *project_owner_method;
                                         /* Method for retrieving the names
					    and emails of the project owners */
  struct access_method *user_data_method;
                                         /* Method for retrieving the user name
					    and real name by his uid */
  struct archive_descr archive;          /* Archivation data */
};


/* Type of file in a triplet */
enum file_type
  {
    file_dist,             /* Something to be distributed */
    file_signature,        /* Detached signature (.sig) */
    file_directive,        /* Directive (.directive.asc) */ 
  };
#define FILE_TYPE_COUNT (file_directive+1)

/* Part of a triplet */
struct file_info
{
  enum file_type type;     /* Part type */
  char *name;              /* File name */
  unsigned root_len;       /* Length of root part in name */ 
  struct stat sb;
};

/* File triplet */
struct file_triplet
{
  char *name;              /* Triplet base name */
  gid_t gid;               /* Owner GID */
  struct file_info file[FILE_TYPE_COUNT]; /* Components */
  struct directory_pair *dpair; /* Owning directory pair */
  char **directive;        /* Decoded directive pairs (key: value\0) */
  char *blurb;             /* Block of directives: directive[i] points here */
  char *tmp;               /* Temporary storage */
  size_t tmpsize;          /* Size of memory allocated in tmp */
  /* Special data for template formatting */
  char *project;           /* Triplet project name (if known) */
  char *user;              /* User name (if known) */
  char **user_data;
};

/* Macros to access owner UID and GID. */
/* The directive file is always present in the triplet */
#define TRIPLET_UID(t) ((t)->file[file_directive].sb.st_uid)
/* GID is filled in after the triplet is finalized and verified */
#define TRIPLET_GID(t) ((t)->gid)

enum wydawca_stat
  {
    STAT_ERRORS,
    STAT_WARNINGS,
    STAT_BAD_SIGNATURE,
    STAT_ACCESS_VIOLATIONS,
    STAT_COMPLETE_TRIPLETS,
    STAT_INCOMPLETE_TRIPLETS,
    STAT_BAD_TRIPLETS,
    STAT_EXPIRED_TRIPLETS,
    STAT_TRIPLET_SUCCESS,
    STAT_UPLOADS,
    STAT_ARCHIVES,
    STAT_SYMLINKS,
    STAT_RMSYMLINKS,
    MAX_STAT 
  };

#define STAT_MASK(c) (1<<(c))
#define STAT_MASK_NONE 0
#define STAT_MASK_ALL  (STAT_MASK(MAX_STAT) - 1)


enum notification_event
  {
    ev_success,
    ev_bad_ownership,
    ev_bad_directive_signature,
    ev_bad_detached_signature,
    MAX_EVENT
  };

enum notification_target
  {
    notify_admin,        /* System administrator */
    notify_owner,        /* Project admin */
    notify_user          /* User (uploader) */
  };

struct message_template;
struct message_template *find_message_template (char *name);
void register_notification (enum notification_event ev,
			    enum notification_target tgt,
			    struct message_template *msg);

void notify (struct file_triplet *, enum notification_event);

const char *notification_event_str (enum notification_event evt);
const char *notification_target_str (enum notification_target tgt);


struct kw_expansion
{
  char *kw;
  char *value;
  int static_p;
  char *(*expand) (struct kw_expansion *, void *data);
  void *data;
};

char *expand_param (const char *param, struct kw_expansion *exp,
		    size_t nexp, void *data);
void escape_kwexp (struct access_method *method, struct kw_expansion *exp,
		   size_t nexp);
void free_kwexp (struct kw_expansion *exp, size_t nexp);
void make_default_kwexp (struct kw_expansion kwexp[4], const char *user,
			const char *project);


/* Global variables */
extern char *conffile;         /* Configuration file name */ 
extern int debug_level;        /* Debugging level */
extern int dry_run_mode;       /* Dry run indicator */
extern int log_to_stderr;      /* Log to stderr instead of the syslog */
extern int log_facility;       /* Syslog facility to use if !log_to_stderr */
extern char *syslog_tag;       /* Syslog tag */
extern int syslog_include_prio;/* Syslog priority indication */
extern time_t file_sweep_time; /* Unlink stale file after this amount of time
				*/
extern char *tar_command_name; /* Name of the tar command */
extern unsigned wydawca_stat[MAX_STAT];
extern unsigned long print_stats;

#define UPDATE_STATS(what)			\
  do						\
    {						\
      if (what >= MAX_STAT) abort();		\
      wydawca_stat[what]++;			\
    }						\
  while (0)

int stat_mask_p (unsigned long mask);
void make_stat_expansion (struct kw_expansion *exp);


/* Utility functions */
char *safe_file_name (char *file_name);
char *safe_file_name_alloc (const char *file_name);
size_t trim_length (const char *str);
size_t trim (char *str);
void logmsg (int prio, char *fmt, ...) GSC_PRINTFLIKE(2,3);
int test_dir (const char *name, int *ec);
char *create_directory (const char *base, const char *name,
			uid_t uid, gid_t gid);
void parse_config (void);
void log_output (int prio, const char *prog, FILE *fp);

enum exec_result
  {
    exec_success,    /* Command executed and returned 0 */
    exec_fail,       /* Command executed and returned not 0 */
    exec_error       /* Command failed to execute */
  };

enum exec_result wydawca_exec (int argc, const char **argv, int *retcode);


/* Directory scanning and registering */
void scan_directories (void);
void register_directory_pair (struct directory_pair *dpair);
void register_file (struct file_info *finfo);
void enumerate_triplets (struct directory_pair *);
size_t count_collected_triplets (void);
char *triplet_expand_param (const char *tmpl, struct file_triplet *trp);

/* General-purpose method support */
struct access_method *method_new (enum access_method_type type);
int method_init (struct access_method *method);
int method_done (struct access_method *method);
int method_run (struct access_method *method, const char *cmd);
void method_copy_result (struct access_method *method, const char *res,
			 size_t size);
const char *method_result (struct access_method *method, unsigned nrow,
			   unsigned ncol);
unsigned method_num_rows (struct access_method *method);
unsigned method_num_cols (struct access_method *method);

/* Verification functions */
int verify_directive_file (struct file_triplet *trp,
			   struct directory_pair *dpair);
int verify_directive_signature (struct file_triplet *trp,
				struct directory_pair *dpair,
				const char *pubkey);
int verify_detached_signature (struct file_triplet *trp,
			       struct directory_pair *dpair);
int fill_project_name (struct file_triplet *trp);

/* Directive file support */
int directive_parse (struct file_triplet *trp);
int directive_get_value (struct file_triplet *trp, const char *key,
			 const char **pval);
int directive_pack_version (const char *val, unsigned *pversion);
int directive_version_in_range_p (struct file_triplet *trp,
				  unsigned from, unsigned to);
int verify_directive_format (struct file_triplet *trp);
int directive_first (struct file_triplet *trp,
		     const char **pkey, const char **pval);
int directive_next (struct file_triplet *trp, int n,
		    const char **pkey, const char **pval);
int process_directives (struct file_triplet *trp,
			struct directory_pair *dpair);


/* Actions */

int move_file (struct file_triplet *trp, struct directory_pair *dpair,
	       enum file_type file_id, const char *reldir);
int archive_file (struct file_triplet *trp, struct directory_pair *dpair,
		  const char *file_name, const char *reldir);	  
int symlink_file (struct file_triplet *trp, struct directory_pair *dpair,
		  const char *reldir,
		  const char *wanted_src, const char *wanted_dst);
int rmsymlink_file (struct file_triplet *trp, struct directory_pair *dpair,
		    const char *reldir, const char *file_name);


Return to:

Send suggestions and report system problems to the System administrator.