make portable to 64bit/32bit
[tridge/hacksm.git] / common.c
1 /*
2   a test implementation of a HSM daemon
3
4   Andrew Tridgell August 2008
5
6  */
7
8 #include "hacksm.h"
9
10 static const struct {
11         dm_eventtype_t ev;
12         const char *name;
13 } dmapi_event_strings[] = {
14 #define EVENT_STRING(x) { x, #x }
15         EVENT_STRING(DM_EVENT_INVALID),
16         EVENT_STRING(DM_EVENT_CLOSE),
17         EVENT_STRING(DM_EVENT_MOUNT),
18         EVENT_STRING(DM_EVENT_PREUNMOUNT),
19         EVENT_STRING(DM_EVENT_UNMOUNT),
20         EVENT_STRING(DM_EVENT_NOSPACE),
21         EVENT_STRING(DM_EVENT_DEBUT),
22         EVENT_STRING(DM_EVENT_CREATE),
23         EVENT_STRING(DM_EVENT_POSTCREATE),
24         EVENT_STRING(DM_EVENT_REMOVE),
25         EVENT_STRING(DM_EVENT_POSTREMOVE),
26         EVENT_STRING(DM_EVENT_RENAME),
27         EVENT_STRING(DM_EVENT_POSTRENAME),
28         EVENT_STRING(DM_EVENT_SYMLINK),
29         EVENT_STRING(DM_EVENT_POSTSYMLINK),
30         EVENT_STRING(DM_EVENT_LINK),
31         EVENT_STRING(DM_EVENT_POSTLINK),
32         EVENT_STRING(DM_EVENT_READ),
33         EVENT_STRING(DM_EVENT_WRITE),
34         EVENT_STRING(DM_EVENT_TRUNCATE),
35         EVENT_STRING(DM_EVENT_ATTRIBUTE),
36         EVENT_STRING(DM_EVENT_CANCEL),
37         EVENT_STRING(DM_EVENT_DESTROY),
38         EVENT_STRING(DM_EVENT_USER),
39         EVENT_STRING(DM_EVENT_PREPERMCHANGE),
40         EVENT_STRING(DM_EVENT_POSTPERMCHANGE),
41         EVENT_STRING(DM_EVENT_MAX),
42 };
43
44 const char *dmapi_event_string(dm_eventtype_t ev)
45 {
46         int i;
47         for (i=0;i<sizeof(dmapi_event_strings)/sizeof(dmapi_event_strings[0]);i++) {
48                 if (dmapi_event_strings[i].ev == ev) {
49                         return dmapi_event_strings[i].name;
50                 }
51         }
52         return "UNKNOWN";
53 }
54
55 void hsm_recover_session(const char *name, dm_sessid_t *sid)
56 {
57         int ret, i;
58         u_int n = 0;
59         dm_sessid_t *sess = NULL;
60         dm_sessid_t oldsid = DM_NO_SESSION;
61
62         ret = dm_getall_sessions(0, NULL, &n);
63         if (ret == 0) {
64                 goto new_session;
65         }
66         if (errno != E2BIG) {
67                 printf("Bad error code %s from dm_getall_sessions\n", strerror(errno));
68                 exit(1);
69         }
70
71         sess = (dm_sessid_t *)calloc(sizeof(dm_sessid_t), n);
72         if (sess == NULL) {
73                 printf("No memory for %u sessions\n", n);
74                 exit(1);
75         }
76
77         ret = dm_getall_sessions(n, sess, &n);
78         if (ret != 0) {
79                 printf("dm_getall_sessions failed\n");
80                 exit(1);
81         }
82
83         for (i=0;i<n;i++) {
84                 char buf[DM_SESSION_INFO_LEN+1] = "";
85                 size_t len = 0;
86
87                 ret = dm_query_session(sess[i], DM_SESSION_INFO_LEN, buf, &len);
88                 if (ret != 0) {
89                         continue;
90                 }
91                 buf[len] = 0;
92                 if (strcmp(buf, name) == 0) {
93                         printf("Recovered existing session\n");
94                         oldsid = sess[i];
95                         break;
96                 }
97         }
98         free(sess);
99
100 new_session:
101         ret = dm_create_session(oldsid, discard_const(name), sid);
102         if (ret != 0) {
103                 printf("Failed to create session\n");
104                 exit(1);
105         }
106 }
107
108
109 int hsm_store_open(dev_t device, ino_t inode, int flags)
110 {
111         char *fname = NULL;
112         asprintf(&fname, HSM_STORE "/0x%llx:0x%llx",
113                  (unsigned long long)device, (unsigned long long)inode);
114         int fd = open(fname, flags, 0600);
115         free(fname);
116         return fd;
117 }
118
119 int hsm_store_unlink(dev_t device, ino_t inode)
120 {
121         char *fname = NULL;
122         int ret;
123         asprintf(&fname, HSM_STORE "/0x%llx:0x%llx",
124                  (unsigned long long)device, (unsigned long long)inode);
125         ret = unlink(fname);
126         free(fname);
127         return ret;
128 }
129
130 void msleep(int t)
131 {
132         struct timeval tval;  
133
134         tval.tv_sec = 0;
135         tval.tv_usec = t;
136  
137         select(0,NULL,NULL, NULL, &tval);
138 }
139
140 void hsm_cleanup_tokens(dm_sessid_t sid, dm_response_t response, int retcode)
141 {
142         dm_token_t *tok = NULL;
143         u_int n = 0;
144         int ret, i, total=0;
145
146         while (1) {
147                 u_int n2;
148                 ret = dm_getall_tokens(sid, n, tok, &n2);
149                 if (ret == -1 && errno == E2BIG) {
150                         n = n2;
151                         tok = realloc(tok, sizeof(dm_token_t)*n);
152                         continue;
153                 }
154                 if (ret == -1) {
155                         printf("dm_getall_tokens - %s\n", strerror(errno));
156                         return;
157                 }
158                 if (ret == 0 && n2 == 0) {
159                         break;
160                 }
161                 printf("Cleaning up %u tokens\n", n2);
162                 for (i=0;i<n2;i++) {
163                         dm_respond_event(sid, tok[i], 
164                                          response, retcode, 0, NULL);
165                         total++;
166                 }
167         }
168         if (tok) free(tok);
169 }
170
171 const char *timestring(void)
172 {
173         time_t t = time(NULL);
174         struct tm *tm = localtime(&t);
175         static char TimeBuf[100];
176
177         strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %T",tm);
178         return TimeBuf;
179 }