Clarify types in auth
[blerg.git] / database / subscription.c
1 /* Blerg is (C) 2011 The Dominion of Awesome, and is distributed under a
2  * BSD-style license.  Please see the COPYING file for details.
3  */
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <sys/mman.h>
7 #include <stdlib.h>
8 #include <stdio.h>
9 #include <fcntl.h>
10 #include <string.h>
11 #include "subscription.h"
12 #include "stringbucket.h"
13 #include "config.h"
14 #include "configuration.h"
15
16 int subscription_add(const char *from, const char *to) {
17         char filename[FILENAME_MAX];
18         struct stringbucket * sb;
19
20         snprintf(filename, FILENAME_MAX, "%s/%s/subscriptions", blergconf.data_path, from);
21         sb = stringbucket_open(filename);
22         stringbucket_add(sb, to);
23         stringbucket_close(sb);
24
25         snprintf(filename, FILENAME_MAX, "%s/%s/subscribers", blergconf.data_path, to);
26         sb = stringbucket_open(filename);
27         stringbucket_add(sb, from);
28         stringbucket_close(sb);
29
30         return 1;
31 }
32
33 int subscription_remove(const char *from, const char *to) {
34         char filename[FILENAME_MAX];
35         struct stringbucket * sb;
36
37         snprintf(filename, FILENAME_MAX, "%s/%s/subscriptions", blergconf.data_path, from);
38         sb = stringbucket_open(filename);
39         stringbucket_delete(sb, to);
40         stringbucket_close(sb);
41
42         snprintf(filename, FILENAME_MAX, "%s/%s/subscribers", blergconf.data_path, to);
43         sb = stringbucket_open(filename);
44         stringbucket_delete(sb, from);
45         stringbucket_close(sb);
46
47         return 1;
48 }
49
50 void subscription_notify_add_item(char *to, void *stuff) {
51         char filename[FILENAME_MAX];
52
53         snprintf(filename, FILENAME_MAX, "%s/%s/subscription_feed", blergconf.data_path, to);
54         int fd = open(filename, O_WRONLY | O_APPEND | O_CREAT, 0600);
55         write(fd, stuff, sizeof(struct blergref));
56         close(fd);
57 }
58
59 int subscription_notify(const char *author, uint64_t record) {
60         char filename[FILENAME_MAX];
61         struct blergref r;
62
63         strncpy(r.author, author, 32);
64         r.record = record;
65
66         snprintf(filename, FILENAME_MAX, "%s/%s/subscribers", blergconf.data_path, author);
67         struct stringbucket * sb = stringbucket_open(filename);
68         stringbucket_iterate(sb, subscription_notify_add_item, &r);
69         stringbucket_close(sb);
70
71         return 1;
72 }
73
74 struct blergref * subscription_list(const char *author, uint64_t offset, int *count, int direction) {
75         char filename[FILENAME_MAX];
76         struct stat st;
77         struct blergref * slist;
78         struct blergref * retlist;
79         uint64_t n_subscription_records;
80
81         if (!valid_name(author))
82                 return NULL;
83
84         snprintf(filename, FILENAME_MAX, "%s/%s/subscription_feed", blergconf.data_path, author);
85
86         int feed_fd = open(filename, O_RDONLY);
87         if (feed_fd == -1) {
88                 perror("Could not open subscription feed");
89                 goto subscription_list_map_failed;
90         }
91
92         fstat(feed_fd, &st);
93         if (st.st_size == 0) {
94                 close(feed_fd);
95                 goto subscription_list_map_failed;
96         }
97         n_subscription_records = st.st_size / sizeof(struct blergref);
98         if (*count > n_subscription_records - offset)
99                 *count = n_subscription_records - offset;
100         if (offset > n_subscription_records) {
101                 fprintf(stderr, "Cannot access subscription record beyond end\n");
102                 goto subscription_list_map_failed;
103                 close(feed_fd);
104                 return NULL;
105         }
106
107         slist = (struct blergref *) mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, feed_fd, 0);
108         if (slist == MAP_FAILED) {
109                 perror("Could not mmap tag_file");
110                 goto subscription_list_map_failed;
111         }
112         retlist = (struct blergref *) malloc(sizeof(struct blergref) * *count);
113         if (retlist == NULL) {
114                 perror("Could not allocate memory for subscription feed list");
115                 goto subscription_list_malloc_failed;
116         }
117         
118         switch(direction) {
119         case 1:
120                 memcpy(retlist, slist + offset, sizeof(struct blergref) * *count);
121                 break;
122         case -1:
123                 memcpy(retlist, slist + (n_subscription_records - *count - offset), sizeof(struct blergref) * *count);
124         }
125
126         munmap(slist, st.st_size);
127         close(feed_fd);
128         return retlist;
129
130 subscription_list_malloc_failed:
131         munmap(slist, st.st_size);
132 subscription_list_map_failed:
133         close(feed_fd);
134 subscription_list_open_failed:
135         *count = 0;
136         return NULL;
137 }
138
139 int is_subscribed(const char *from, const char *to) {
140         char filename[FILENAME_MAX];
141         struct stringbucket * sb;
142         int ret = 0;
143
144         snprintf(filename, FILENAME_MAX, "%s/%s/subscriptions", blergconf.data_path, from);
145         sb = stringbucket_open(filename);
146         if (stringbucket_find(sb, to) != -1)
147                 ret = 1;
148         stringbucket_close(sb);
149
150         return ret;
151 }
152
153 int subscription_count_items(const char *user) {
154         char filename[FILENAME_MAX];
155         struct stat st;
156
157         if (!valid_name(user))
158                 return -1;
159
160         snprintf(filename, FILENAME_MAX, "%s/%s/subscription_feed", blergconf.data_path, user);
161
162         if (access(filename, R_OK) != 0)
163                 return 0;
164         stat(filename, &st);
165         return st.st_size / sizeof(struct blergref);
166 }