added demo of signal/uid handling feature
[tridge/junkcode.git] / isoffline.c
1 /*
2   demonstration of checking if a file is offline using DMAPI, with
3   shortcut tricks using st_atime and st_blocks
4
5   Build with
6       gcc -o isoffline isoffline.c -ldmapi
7
8   Andrew Tridgell (tridgell@au1.ibm.com) July 2007
9  */
10
11 #include <stdio.h>
12 #include <dmapi.h>
13 #include <stdbool.h>
14 #include <stdint.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <time.h>
18 #include <errno.h>
19 #include <sys/stat.h>
20
21 /* optimisation tunables - used to avoid the DMAPI slow path */
22 #define FILE_IS_ONLINE_RATIO      0.5
23 #define FILE_IS_ONLINE_ATIME      60
24
25
26 /*
27   see if a file is offline
28
29   return -1 on failure. Set *offline to true/false according to
30   offline status
31  */
32 static int is_offline(char *fname, time_t now, bool *offline)
33 {
34         struct stat st;
35         void *handle=NULL;
36         size_t handle_len=0;
37         size_t rlen;
38         int ret;
39         dm_attrname_t dmAttrName;
40         /* keep some state between calls, to save on session creation calls */
41         static struct dmapi_state {
42                 dm_sessid_t sid;
43                 void *handle;
44                 size_t handle_len;
45         } state;
46
47         if (state.sid == 0) {
48                 /* create a new session if needed */
49                 if (dm_create_session(DM_NO_SESSION, "samba", &state.sid) != 0) {
50                         return -1;
51                 }
52         }
53
54         /* try shortcut methods first */
55         if (stat(fname, &st) != 0) {
56                 return -1;
57         }
58
59         /* if the file has more than FILE_IS_ONLINE_RATIO of blocks available,
60            then assume its not offline (it may not be 100%, as it could be sparse) */
61         if (512 * (off_t)st.st_blocks > st.st_size * FILE_IS_ONLINE_RATIO) {
62                 *offline = false;
63                 return 0;
64         }
65
66         /* go the slow DMAPI route */
67         if (dm_path_to_handle(fname, &handle, &handle_len) != 0) {
68                 return -1;
69         }
70
71         memset(&dmAttrName, 0, sizeof(dmAttrName));
72         strcpy((char *)&dmAttrName.an_chars[0], "IBMObj");
73
74         ret = dm_get_dmattr(state.sid, handle, handle_len, 
75                             DM_NO_TOKEN, &dmAttrName, 0, NULL, &rlen);
76
77         /* its offline if the IBMObj attribute exists */
78         *offline = (ret == 0 || (ret == -1 && errno == E2BIG));
79
80         dm_handle_free(handle, handle_len);
81         return 0;       
82 }
83
84
85 int main(int argc, char *argv[])
86 {
87         int i;
88         time_t now = time(NULL);
89         now = time(NULL);
90         if (argc < 2) {
91                 printf("isoffline <fname...>\n");
92                 exit(1);
93         }
94         for (i=1;i<argc;i++) {
95                 bool offline;
96                 if (is_offline(argv[i], now, &offline) == -1) {
97                         perror(argv[i]);
98                         exit(1);
99                 }
100                 printf("%s\t%s\n", offline?"offline":"online ", argv[i]);
101         }
102         return 0;
103 }