added some tools from ronnie sahlberg
[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 <sys/stat.h>
19
20 /* optimisation tunables - used to avoid the DMAPI slow path */
21 #define FILE_IS_ONLINE_RATIO      0.5
22 #define FILE_IS_ONLINE_ATIME      60
23
24
25 /*
26   see if a file is offline
27
28   return -1 on failure. Set *offline to true/false according to
29   offline status
30  */
31 static int is_offline(char *fname, time_t now, bool *offline)
32 {
33         struct stat st;
34         void *handle;
35         size_t handle_len;
36         size_t rlen;
37         int ret;
38         dm_attrname_t dmAttrName;
39         /* keep some state between calls, to save on session creation calls */
40         static struct dmapi_state {
41                 dm_sessid_t sid;
42                 void *handle;
43                 size_t handle_len;
44         } state;
45
46         if (state.sid == 0) {
47                 /* create a new session if needed */
48                 if (dm_create_session(DM_NO_SESSION, "samba", &state.sid) != 0) {
49                         return -1;
50                 }
51         }
52
53         /* try shortcut methods first */
54         if (stat(fname, &st) != 0) {
55                 return -1;
56         }
57
58         /* if the file has more than FILE_IS_ONLINE_RATIO of blocks available,
59            then assume its not offline (it may not be 100%, as it could be sparse) */
60         if (512 * (off_t)st.st_blocks > st.st_size * FILE_IS_ONLINE_RATIO) {
61                 *offline = false;
62                 return 0;
63         }
64
65         /* go the slow DMAPI route */
66         if (dm_path_to_handle(fname, &handle, &handle_len) != 0) {
67                 return -1;
68         }
69
70         memset(&dmAttrName, 0, sizeof(dmAttrName));
71         strcpy((char *)&dmAttrName.an_chars[0], "IBMObj");
72
73         ret = dm_get_dmattr(state.sid, handle, handle_len, 
74                             DM_NO_TOKEN, &dmAttrName, 0, NULL, &rlen);
75
76         /* its offline if the IBMObj attribute exists */
77         *offline = (ret == 0 || (ret == -1 && errno == E2BIG));
78
79         dm_handle_free(handle, handle_len);
80         return 0;       
81 }
82
83
84 int main(int argc, char *argv[])
85 {
86         int i;
87         time_t now = time(NULL);
88         now = time(NULL);
89         if (argc < 2) {
90                 printf("isoffline <fname...>\n");
91                 exit(1);
92         }
93         for (i=1;i<argc;i++) {
94                 bool offline;
95                 if (is_offline(argv[i], now, &offline) == -1) {
96                         perror(argv[i]);
97                         exit(1);
98                 }
99                 printf("%s\t%s\n", offline?"offline":"online ", argv[i]);
100         }
101         return 0;
102 }