2 demonstration of checking if a file is offline using DMAPI, with
3 shortcut tricks using st_atime and st_blocks
6 gcc -o isoffline isoffline.c -ldmapi
8 Andrew Tridgell (tridgell@au1.ibm.com) July 2007
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
25 #define DMAPI_SESSION_NAME "samba"
26 #define DMAPI_TRACE 10
28 static dm_sessid_t samba_dmapi_session = DM_NO_SESSION;
30 #define DEBUG(lvl, x) printf x
31 #define DEBUGADD(lvl, x) printf x
34 Initialise DMAPI session. The session is persistant kernel state,
35 so it might already exist, in which case we merely want to
36 reconnect to it. This function should be called as root.
38 static int dmapi_init_session(void)
40 char buf[DM_SESSION_INFO_LEN];
43 dm_sessid_t *sessions = NULL;
47 if (dm_init_service(&version) < 0) {
48 DEBUG(0,("dm_init_service failed - disabling DMAPI\n"));
55 dm_sessid_t *new_sessions;
57 new_sessions = TALLOC_REALLOC_ARRAY(NULL, sessions,
58 dm_sessid_t, nsessions);
59 if (new_sessions == NULL) {
60 talloc_free(sessions);
63 sessions = new_sessions;
64 err = dm_getall_sessions(nsessions, sessions, &nsessions);
65 } while (err == -1 && errno == E2BIG);
69 ("failed to retrieve DMAPI sessions: %s\n",
71 talloc_free(sessions);
75 for (i = 0; i < nsessions; ++i) {
76 err = dm_query_session(sessions[i], sizeof(buf), buf, &buflen);
77 buf[sizeof(buf) - 1] = '\0';
78 if (err == 0 && strcmp(DMAPI_SESSION_NAME, buf) == 0) {
79 samba_dmapi_session = sessions[i];
81 ("attached to existing DMAPI session "
82 "named '%s'\n", buf));
87 talloc_free(sessions);
89 /* No session already defined. */
90 if (samba_dmapi_session == DM_NO_SESSION) {
91 err = dm_create_session(DM_NO_SESSION, DMAPI_SESSION_NAME,
92 &samba_dmapi_session);
95 ("failed to create new DMAPI session: %s\n",
97 samba_dmapi_session = DM_NO_SESSION;
101 DEBUG(0,("created new DMAPI session named '%s' for %s\n",
102 DMAPI_SESSION_NAME, version));
105 if (samba_dmapi_session != DM_NO_SESSION) {
106 set_effective_capability(DMAPI_ACCESS_CAPABILITY);
110 Note that we never end the DMAPI session. It gets re-used
119 return a pointer to our dmapi session if available
120 This assumes you have called dmapi_have_session() first
122 const void *dmapi_get_current_session(void)
124 if (samba_dmapi_session == DM_NO_SESSION) {
127 return (void *)&samba_dmapi_session;
131 this must be the first dmapi call you make in Samba. It will initialise dmapi
132 if available and tell you if you can get a dmapi session. This should be called in
133 the client specific child process
135 BOOL dmapi_have_session(void)
137 static BOOL initialised;
141 dmapi_init_session();
144 return samba_dmapi_session != DM_NO_SESSION;
149 see if a file is offline
151 return -1 on failure. Set *offline to true/false according to
154 static int is_offline(char *fname, time_t now, bool *offline)
161 dm_attrname_t dmAttrName;
162 /* keep some state between calls, to save on session creation calls */
163 static struct dmapi_state {
169 if (state.sid == 0) {
170 /* create a new session if needed */
171 if (dm_create_session(DM_NO_SESSION, "samba", &state.sid) != 0) {
176 /* try shortcut methods first */
177 if (stat(fname, &st) != 0) {
181 /* if the file has more than FILE_IS_ONLINE_RATIO of blocks available,
182 then assume its not offline (it may not be 100%, as it could be sparse) */
183 if (512 * (off_t)st.st_blocks > st.st_size * FILE_IS_ONLINE_RATIO) {
188 /* go the slow DMAPI route */
189 if (dm_path_to_handle(fname, &handle, &handle_len) != 0) {
193 memset(&dmAttrName, 0, sizeof(dmAttrName));
194 strcpy((char *)&dmAttrName.an_chars[0], "IBMObj");
196 ret = dm_get_dmattr(state.sid, handle, handle_len,
197 DM_NO_TOKEN, &dmAttrName, 0, NULL, &rlen);
199 /* its offline if the IBMObj attribute exists */
200 *offline = (ret == 0 || (ret == -1 && errno == E2BIG));
202 dm_handle_free(handle, handle_len);
207 int main(int argc, char *argv[])
210 time_t now = time(NULL);
213 printf("isoffline <fname...>\n");
216 for (i=1;i<argc;i++) {
218 if (is_offline(argv[i], now, &offline) == -1) {
222 printf("%s\t%s\n", offline?"offline":"online ", argv[i]);