2 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
8 * Copyright (c) 2007, The Storage Networking Industry Association.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * - Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
16 * - Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
21 * - Neither the name of The Storage Networking Industry Association (SNIA)
22 * nor the names of its contributors may be used to endorse or promote
23 * products derived from this software without specific prior written
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
30 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
38 /* Copyright (c) 1996, 1997 PDC, Network Appliance. All Rights Reserved */
39 /* Copyright (c) 2007, The Storage Networking Industry Association. */
42 * File history callback functions called by backup modules. NDMP file history
43 * supports 2 file history models: path based and inode/directory based.
44 * Backup/recover modules similar to unix dump/restore utilize the
45 * inode/directory based model. During the filesystem scan pass,
46 * ndmpd_file_history_dir() is called. During the file backup pass,
47 * ndmpd_file_history_node() is called. This model is appropriate for
48 * modules whose code is structured such that file name and file attribute
49 * data is not available at the same time. Backup/recover modules similar
50 * to tar or cpio utilize the path based model. The simple dump/restore module
51 * included with the SDK uses the path based model.
55 #include <sys/types.h>
65 #define N_PATH_ENTRIES 1000
66 #define N_FILE_ENTRIES N_PATH_ENTRIES
67 #define N_DIR_ENTRIES 1000
68 #define N_NODE_ENTRIES 1000
70 /* Figure an average of 32 bytes per path name */
71 #define PATH_NAMEBUF_SIZE (N_PATH_ENTRIES * 32)
73 /* Figure an average of 16 bytes per file name */
74 #define DIR_NAMEBUF_SIZE (N_PATH_ENTRIES * 16)
76 static boolean_t
fh_requested(void *cookie
);
77 static void ndmpd_file_history_cleanup_v2(ndmpd_session_t
*session
,
79 static void ndmpd_file_history_cleanup_v3(ndmpd_session_t
*session
,
81 static ndmpd_module_params_t
*get_params(void *cookie
);
85 * Each file history as a separate message to the client.
87 static int ndmp_syncfh
= 0;
91 * ************************************************************************
93 * ************************************************************************
97 * ndmpd_api_file_history_path_v2
99 * Add a file history path entry to the buffer.
100 * History data is buffered until the buffer is filled.
101 * Full buffers are then sent to the client.
104 * cookie (input) - session pointer.
105 * name (input) - file name.
106 * NULL forces buffered data to be sent.
107 * file_stat (input) - file status pointer.
108 * fh_info (input) - data stream position of file data used during
116 ndmpd_api_file_history_path_v2(void *cookie
, char *name
,
117 struct stat64
*file_stat
, u_longlong_t fh_info
)
119 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
120 ndmp_fh_unix_path
*entry
;
122 if (name
== NULL
&& session
->ns_fh
.fh_path_index
== 0)
126 * If the buffer does not have space
127 * for the current entry, send the buffered data to the client.
128 * A NULL name indicates that any buffered data should be sent.
131 (ndmp_syncfh
&& session
->ns_fh
.fh_path_index
!= 0) ||
132 session
->ns_fh
.fh_path_index
== N_PATH_ENTRIES
||
133 session
->ns_fh
.fh_path_name_buf_index
+ strlen(name
) + 1 >
135 ndmp_fh_add_unix_path_request request
;
138 "sending %ld entries", session
->ns_fh
.fh_path_index
);
140 request
.paths
.paths_val
= session
->ns_fh
.fh_path_entries
;
141 request
.paths
.paths_len
= session
->ns_fh
.fh_path_index
;
143 if (ndmp_send_request_lock(session
->ns_connection
,
144 NDMP_FH_ADD_UNIX_PATH
, NDMP_NO_ERR
, (void *) &request
,
146 NDMP_LOG(LOG_DEBUG
, "Sending file history data");
149 session
->ns_fh
.fh_path_index
= 0;
150 session
->ns_fh
.fh_path_name_buf_index
= 0;
155 if (session
->ns_fh
.fh_path_entries
== 0) {
156 session
->ns_fh
.fh_path_entries
= ndmp_malloc(N_PATH_ENTRIES
*
157 sizeof (ndmp_fh_unix_path
));
158 if (session
->ns_fh
.fh_path_entries
== 0)
161 if (session
->ns_fh
.fh_path_name_buf
== 0) {
162 session
->ns_fh
.fh_path_name_buf
=
163 ndmp_malloc(PATH_NAMEBUF_SIZE
);
164 if (session
->ns_fh
.fh_path_name_buf
== 0)
167 entry
= &session
->ns_fh
.fh_path_entries
[session
->ns_fh
.fh_path_index
];
168 ndmpd_get_file_entry_type(file_stat
->st_mode
, &entry
->fstat
.ftype
);
170 entry
->name
= &session
->
171 ns_fh
.fh_path_name_buf
[session
->ns_fh
.fh_path_name_buf_index
];
172 (void) strlcpy(entry
->name
, name
, PATH_NAMEBUF_SIZE
);
173 session
->ns_fh
.fh_path_name_buf_index
+= strlen(name
) + 1;
174 entry
->fstat
.mtime
= (ulong_t
)file_stat
->st_mtime
;
175 entry
->fstat
.atime
= (ulong_t
)file_stat
->st_atime
;
176 entry
->fstat
.ctime
= (ulong_t
)file_stat
->st_ctime
;
177 entry
->fstat
.uid
= file_stat
->st_uid
;
178 entry
->fstat
.gid
= file_stat
->st_gid
;
179 entry
->fstat
.mode
= (file_stat
->st_mode
) & 0x0fff;
180 entry
->fstat
.size
= long_long_to_quad((u_longlong_t
)file_stat
->st_size
);
181 entry
->fstat
.fh_info
= long_long_to_quad((u_longlong_t
)fh_info
);
182 session
->ns_fh
.fh_path_index
++;
188 * ndmpd_api_file_history_dir_v2
190 * Add a file history dir entry to the buffer.
191 * History data is buffered until the buffer is filled.
192 * Full buffers are then sent to the client.
195 * cookie (input) - session pointer.
196 * name (input) - file name.
197 * NULL forces buffered data to be sent.
198 * node (input) - file inode.
199 * parent (input) - file parent inode.
200 * Should equal node if the file is the root of
201 * the filesystem and has no parent.
208 ndmpd_api_file_history_dir_v2(void *cookie
, char *name
, ulong_t node
,
211 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
212 ndmp_fh_unix_dir
*entry
;
214 if (name
== NULL
&& session
->ns_fh
.fh_dir_index
== 0)
218 * If the buffer does not have space for the current entry,
219 * send the buffered data to the client. A NULL name indicates
220 * that any buffered data should be sent.
223 (ndmp_syncfh
&& session
->ns_fh
.fh_dir_index
!= 0) ||
224 session
->ns_fh
.fh_dir_index
== N_DIR_ENTRIES
||
225 session
->ns_fh
.fh_dir_name_buf_index
+ strlen(name
) + 1 >
227 ndmp_fh_add_unix_dir_request request
;
230 "sending %ld entries", session
->ns_fh
.fh_dir_index
);
232 request
.dirs
.dirs_val
= session
->ns_fh
.fh_dir_entries
;
233 request
.dirs
.dirs_len
= session
->ns_fh
.fh_dir_index
;
234 if (ndmp_send_request_lock(session
->ns_connection
,
235 NDMP_FH_ADD_UNIX_DIR
, NDMP_NO_ERR
, (void *) &request
,
237 NDMP_LOG(LOG_DEBUG
, "Sending file history data");
240 session
->ns_fh
.fh_dir_index
= 0;
241 session
->ns_fh
.fh_dir_name_buf_index
= 0;
246 if (session
->ns_fh
.fh_dir_entries
== 0) {
247 session
->ns_fh
.fh_dir_entries
= ndmp_malloc(N_DIR_ENTRIES
248 * sizeof (ndmp_fh_unix_dir
));
249 if (session
->ns_fh
.fh_dir_entries
== 0)
252 if (session
->ns_fh
.fh_dir_name_buf
== 0) {
253 session
->ns_fh
.fh_dir_name_buf
= ndmp_malloc(DIR_NAMEBUF_SIZE
);
254 if (session
->ns_fh
.fh_dir_name_buf
== 0)
257 entry
= &session
->ns_fh
.fh_dir_entries
[session
->ns_fh
.fh_dir_index
];
259 entry
->name
= &session
->
260 ns_fh
.fh_dir_name_buf
[session
->ns_fh
.fh_dir_name_buf_index
];
261 (void) strlcpy(&session
->
262 ns_fh
.fh_dir_name_buf
[session
->ns_fh
.fh_dir_name_buf_index
],
263 name
, PATH_NAMEBUF_SIZE
);
264 session
->ns_fh
.fh_dir_name_buf_index
+= strlen(name
) + 1;
267 entry
->parent
= parent
;
269 session
->ns_fh
.fh_dir_index
++;
275 * ndmpd_api_file_history_node_v2
277 * Add a file history node entry to the buffer.
278 * History data is buffered until the buffer is filled.
279 * Full buffers are then sent to the client.
282 * cookie (input) - session pointer.
283 * node (input) - file inode.
284 * must match a node from a prior ndmpd_api_file_history_dir()
286 * file_stat (input) - file status pointer.
287 * 0 forces buffered data to be sent.
288 * fh_info (input) - data stream position of file data used during
296 ndmpd_api_file_history_node_v2(void *cookie
, ulong_t node
,
297 struct stat64
*file_stat
, u_longlong_t fh_info
)
299 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
300 ndmp_fh_unix_node
*entry
;
302 if (file_stat
== NULL
&& session
->ns_fh
.fh_node_index
== 0)
306 * If the buffer does not have space
307 * for the current entry, send the buffered data to the client.
308 * A 0 file_stat pointer indicates that any buffered data should
311 if (file_stat
== NULL
||
312 (ndmp_syncfh
&& session
->ns_fh
.fh_node_index
!= 0) ||
313 session
->ns_fh
.fh_node_index
== N_NODE_ENTRIES
) {
314 ndmp_fh_add_unix_node_request request
;
317 "sending %ld entries", session
->ns_fh
.fh_node_index
);
319 request
.nodes
.nodes_val
= session
->ns_fh
.fh_node_entries
;
320 request
.nodes
.nodes_len
= session
->ns_fh
.fh_node_index
;
322 * Need to send Dir entry as well. Since Dir entry is more than
323 * Node entry, we may send a Node entry that hasn't have
324 * its dir entry sent. Therefore, we need to flush Dir entry
325 * as well everytime the Dir entry is send.
327 (void) ndmpd_api_file_history_dir_v2(session
, 0, 0, 0);
329 if (ndmp_send_request_lock(session
->ns_connection
,
330 NDMP_FH_ADD_UNIX_NODE
, NDMP_NO_ERR
, (void *) &request
,
332 NDMP_LOG(LOG_DEBUG
, "Sending file history data");
335 session
->ns_fh
.fh_node_index
= 0;
337 if (file_stat
== NULL
)
340 if (session
->ns_fh
.fh_node_entries
== 0) {
341 session
->ns_fh
.fh_node_entries
= ndmp_malloc(N_NODE_ENTRIES
342 * sizeof (ndmp_fh_unix_node
));
343 if (session
->ns_fh
.fh_node_entries
== 0)
346 entry
= &session
->ns_fh
.fh_node_entries
[session
->ns_fh
.fh_node_index
];
347 ndmpd_get_file_entry_type(file_stat
->st_mode
, &entry
->fstat
.ftype
);
350 entry
->fstat
.mtime
= (ulong_t
)file_stat
->st_mtime
;
351 entry
->fstat
.atime
= (ulong_t
)file_stat
->st_atime
;
352 entry
->fstat
.ctime
= (ulong_t
)file_stat
->st_ctime
;
353 entry
->fstat
.uid
= file_stat
->st_uid
;
354 entry
->fstat
.gid
= file_stat
->st_gid
;
355 entry
->fstat
.mode
= (file_stat
->st_mode
) & 0x0fff;
356 entry
->fstat
.size
= long_long_to_quad((u_longlong_t
)file_stat
->st_size
);
357 entry
->fstat
.fh_info
= long_long_to_quad(fh_info
);
359 session
->ns_fh
.fh_node_index
++;
365 * ************************************************************************
367 * ************************************************************************
371 * ndmpd_api_file_history_file_v3
373 * Add a file history file entry to the buffer.
374 * History data is buffered until the buffer is filled.
375 * Full buffers are then sent to the client.
378 * cookie (input) - session pointer.
379 * name (input) - file name.
380 * NULL forces buffered data to be sent.
381 * file_stat (input) - file status pointer.
382 * fh_info (input) - data stream position of file data used during
390 ndmpd_api_file_history_file_v3(void *cookie
, char *name
,
391 struct stat64
*file_stat
, u_longlong_t fh_info
)
393 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
394 ndmp_file_v3
*file_entry
;
395 ndmp_file_name_v3
*file_name_entry
;
396 ndmp_file_stat_v3
*file_stat_entry
;
397 ndmp_fh_add_file_request_v3 request
;
399 if (name
== NULL
&& session
->ns_fh_v3
.fh_file_index
== 0)
403 * If the buffer does not have space
404 * for the current entry, send the buffered data to the client.
405 * A NULL name indicates that any buffered data should be sent.
408 session
->ns_fh_v3
.fh_file_index
== N_FILE_ENTRIES
||
409 session
->ns_fh_v3
.fh_file_name_buf_index
+ strlen(name
) + 1 >
412 NDMP_LOG(LOG_DEBUG
, "sending %ld entries",
413 session
->ns_fh_v3
.fh_file_index
);
415 request
.files
.files_len
= session
->ns_fh_v3
.fh_file_index
;
416 request
.files
.files_val
= session
->ns_fh_v3
.fh_files
;
418 if (ndmp_send_request_lock(session
->ns_connection
,
419 NDMP_FH_ADD_FILE
, NDMP_NO_ERR
, (void *) &request
, 0) < 0) {
421 "Sending ndmp_fh_add_file request");
425 session
->ns_fh_v3
.fh_file_index
= 0;
426 session
->ns_fh_v3
.fh_file_name_buf_index
= 0;
432 if (session
->ns_fh_v3
.fh_files
== 0) {
433 session
->ns_fh_v3
.fh_files
= ndmp_malloc(sizeof (ndmp_file_v3
) *
435 if (session
->ns_fh_v3
.fh_files
== 0)
439 if (session
->ns_fh_v3
.fh_file_names
== 0) {
440 session
->ns_fh_v3
.fh_file_names
=
441 ndmp_malloc(sizeof (ndmp_file_name_v3
) * N_FILE_ENTRIES
);
442 if (session
->ns_fh_v3
.fh_file_names
== 0)
446 if (session
->ns_fh_v3
.fh_file_name_buf
== 0) {
447 session
->ns_fh_v3
.fh_file_name_buf
=
448 ndmp_malloc(sizeof (char) * PATH_NAMEBUF_SIZE
);
449 if (session
->ns_fh_v3
.fh_file_name_buf
== 0)
453 if (session
->ns_fh_v3
.fh_file_stats
== 0) {
454 session
->ns_fh_v3
.fh_file_stats
=
455 ndmp_malloc(sizeof (ndmp_file_stat_v3
) * N_FILE_ENTRIES
);
456 if (session
->ns_fh_v3
.fh_file_stats
== 0)
461 &session
->ns_fh_v3
.fh_files
[session
->ns_fh_v3
.fh_file_index
];
463 &session
->ns_fh_v3
.fh_file_names
[session
->ns_fh_v3
.fh_file_index
];
465 &session
->ns_fh_v3
.fh_file_stats
[session
->ns_fh_v3
.fh_file_index
];
466 file_entry
->names
.names_len
= 1;
467 file_entry
->names
.names_val
= file_name_entry
;
468 file_entry
->stats
.stats_len
= 1;
469 file_entry
->stats
.stats_val
= file_stat_entry
;
470 file_entry
->node
= long_long_to_quad(file_stat
->st_ino
);
471 file_entry
->fh_info
= long_long_to_quad(fh_info
);
473 file_name_entry
->fs_type
= NDMP_FS_UNIX
;
474 file_name_entry
->ndmp_file_name_v3_u
.unix_name
=
475 &session
->ns_fh_v3
.fh_file_name_buf
[session
->
476 ns_fh_v3
.fh_file_name_buf_index
];
477 (void) strlcpy(&session
->ns_fh_v3
.fh_file_name_buf
[session
->
478 ns_fh_v3
.fh_file_name_buf_index
], name
, PATH_NAMEBUF_SIZE
);
479 session
->ns_fh_v3
.fh_file_name_buf_index
+= strlen(name
) + 1;
480 ndmpd_get_file_entry_type(file_stat
->st_mode
, &file_stat_entry
->ftype
);
482 file_stat_entry
->invalid
= 0;
483 file_stat_entry
->fs_type
= NDMP_FS_UNIX
;
484 file_stat_entry
->mtime
= file_stat
->st_mtime
;
485 file_stat_entry
->atime
= file_stat
->st_atime
;
486 file_stat_entry
->ctime
= file_stat
->st_ctime
;
487 file_stat_entry
->owner
= file_stat
->st_uid
;
488 file_stat_entry
->group
= file_stat
->st_gid
;
489 file_stat_entry
->fattr
= file_stat
->st_mode
& 0x0fff;
490 file_stat_entry
->size
=
491 long_long_to_quad((u_longlong_t
)file_stat
->st_size
);
492 file_stat_entry
->links
= file_stat
->st_nlink
;
494 session
->ns_fh_v3
.fh_file_index
++;
501 * ndmpd_api_file_history_dir_v3
503 * Add a file history dir entry to the buffer.
504 * History data is buffered until the buffer is filled.
505 * Full buffers are then sent to the client.
508 * cookie (input) - session pointer.
509 * name (input) - file name.
510 * NULL forces buffered data to be sent.
511 * node (input) - file inode.
512 * parent (input) - file parent inode.
513 * Should equal node if the file is the root of
514 * the filesystem and has no parent.
521 ndmpd_api_file_history_dir_v3(void *cookie
, char *name
, ulong_t node
,
524 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
525 ndmp_dir_v3
*dir_entry
;
526 ndmp_file_name_v3
*dir_name_entry
;
527 ndmp_fh_add_dir_request_v3 request
;
529 if (name
== NULL
&& session
->ns_fh_v3
.fh_dir_index
== 0)
533 * If the buffer does not have space
534 * for the current entry, send the buffered data to the client.
535 * A NULL name indicates that any buffered data should be sent.
538 session
->ns_fh_v3
.fh_dir_index
== N_DIR_ENTRIES
||
539 session
->ns_fh_v3
.fh_dir_name_buf_index
+ strlen(name
) + 1 >
542 NDMP_LOG(LOG_DEBUG
, "sending %ld entries",
543 session
->ns_fh_v3
.fh_dir_index
);
545 request
.dirs
.dirs_val
= session
->ns_fh_v3
.fh_dirs
;
546 request
.dirs
.dirs_len
= session
->ns_fh_v3
.fh_dir_index
;
548 if (ndmp_send_request_lock(session
->ns_connection
,
549 NDMP_FH_ADD_DIR
, NDMP_NO_ERR
, (void *) &request
, 0) < 0) {
551 "Sending ndmp_fh_add_dir request");
555 session
->ns_fh_v3
.fh_dir_index
= 0;
556 session
->ns_fh_v3
.fh_dir_name_buf_index
= 0;
562 if (session
->ns_fh_v3
.fh_dirs
== 0) {
563 session
->ns_fh_v3
.fh_dirs
=
564 ndmp_malloc(sizeof (ndmp_dir_v3
) * N_DIR_ENTRIES
);
565 if (session
->ns_fh_v3
.fh_dirs
== 0)
569 if (session
->ns_fh_v3
.fh_dir_names
== 0) {
570 session
->ns_fh_v3
.fh_dir_names
=
571 ndmp_malloc(sizeof (ndmp_file_name_v3
) * N_DIR_ENTRIES
);
572 if (session
->ns_fh_v3
.fh_dir_names
== 0)
576 if (session
->ns_fh_v3
.fh_dir_name_buf
== 0) {
577 session
->ns_fh_v3
.fh_dir_name_buf
=
578 ndmp_malloc(sizeof (char) * DIR_NAMEBUF_SIZE
);
579 if (session
->ns_fh_v3
.fh_dir_name_buf
== 0)
583 dir_entry
= &session
->ns_fh_v3
.fh_dirs
[session
->ns_fh_v3
.fh_dir_index
];
585 &session
->ns_fh_v3
.fh_dir_names
[session
->ns_fh_v3
.fh_dir_index
];
587 dir_name_entry
->fs_type
= NDMP_FS_UNIX
;
588 dir_name_entry
->ndmp_file_name_v3_u
.unix_name
=
589 &session
->ns_fh_v3
.fh_dir_name_buf
[session
->
590 ns_fh_v3
.fh_dir_name_buf_index
];
592 (void) strlcpy(&session
->ns_fh_v3
.fh_dir_name_buf
[session
->
593 ns_fh_v3
.fh_dir_name_buf_index
], name
, PATH_NAMEBUF_SIZE
);
594 session
->ns_fh_v3
.fh_dir_name_buf_index
+= strlen(name
) + 1;
596 dir_entry
->names
.names_len
= 1;
597 dir_entry
->names
.names_val
= dir_name_entry
;
598 dir_entry
->node
= long_long_to_quad(node
);
599 dir_entry
->parent
= long_long_to_quad(parent
);
601 session
->ns_fh_v3
.fh_dir_index
++;
608 * ndmpd_api_file_history_node_v3
610 * Add a file history node entry to the buffer.
611 * History data is buffered until the buffer is filled.
612 * Full buffers are then sent to the client.
615 * cookie (input) - session pointer.
616 * node (input) - file inode.
617 * must match a node from a prior ndmpd_api_file_history_dir()
619 * file_stat (input) - file status pointer.
620 * 0 forces buffered data to be sent.
621 * fh_info (input) - data stream position of file data used during
629 ndmpd_api_file_history_node_v3(void *cookie
, ulong_t node
,
630 struct stat64
*file_stat
, u_longlong_t fh_info
)
632 ndmpd_session_t
*session
= (ndmpd_session_t
*)cookie
;
633 ndmp_node_v3
*node_entry
;
634 ndmp_file_stat_v3
*file_stat_entry
;
635 ndmp_fh_add_node_request_v3 request
;
637 if (file_stat
== NULL
&& session
->ns_fh_v3
.fh_node_index
== 0)
641 * If the buffer does not have space
642 * for the current entry, send the buffered data to the client.
643 * A 0 file_stat pointer indicates that any buffered data should
646 if (file_stat
== NULL
||
647 session
->ns_fh_v3
.fh_node_index
== N_NODE_ENTRIES
) {
648 NDMP_LOG(LOG_DEBUG
, "sending %ld entries",
649 session
->ns_fh_v3
.fh_node_index
);
652 * Need to send Dir entry as well. Since Dir entry is more
653 * than a Node entry, we may send a Node entry that hasn't
654 * had its Dir entry sent. Therefore, we need to flush Dir
655 * entry as well every time the Dir entry is sent.
657 (void) ndmpd_api_file_history_dir_v3(session
, 0, 0, 0);
659 request
.nodes
.nodes_len
= session
->ns_fh_v3
.fh_node_index
;
660 request
.nodes
.nodes_val
= session
->ns_fh_v3
.fh_nodes
;
662 if (ndmp_send_request_lock(session
->ns_connection
,
664 NDMP_NO_ERR
, (void *) &request
, 0) < 0) {
666 "Sending ndmp_fh_add_node request");
670 session
->ns_fh_v3
.fh_node_index
= 0;
673 if (file_stat
== NULL
)
676 if (session
->ns_fh_v3
.fh_nodes
== 0) {
677 session
->ns_fh_v3
.fh_nodes
=
678 ndmp_malloc(sizeof (ndmp_node_v3
) * N_NODE_ENTRIES
);
679 if (session
->ns_fh_v3
.fh_nodes
== 0)
683 if (session
->ns_fh_v3
.fh_node_stats
== 0) {
684 session
->ns_fh_v3
.fh_node_stats
=
685 ndmp_malloc(sizeof (ndmp_file_stat_v3
) * N_NODE_ENTRIES
);
686 if (session
->ns_fh_v3
.fh_node_stats
== 0)
691 &session
->ns_fh_v3
.fh_nodes
[session
->ns_fh_v3
.fh_node_index
];
694 &session
->ns_fh_v3
.fh_node_stats
[session
->ns_fh_v3
.fh_node_index
];
695 ndmpd_get_file_entry_type(file_stat
->st_mode
, &file_stat_entry
->ftype
);
697 file_stat_entry
->invalid
= 0;
698 file_stat_entry
->fs_type
= NDMP_FS_UNIX
;
699 file_stat_entry
->mtime
= file_stat
->st_mtime
;
700 file_stat_entry
->atime
= file_stat
->st_atime
;
701 file_stat_entry
->ctime
= file_stat
->st_ctime
;
702 file_stat_entry
->owner
= file_stat
->st_uid
;
703 file_stat_entry
->group
= file_stat
->st_gid
;
704 file_stat_entry
->fattr
= file_stat
->st_mode
& 0x0fff;
705 file_stat_entry
->size
=
706 long_long_to_quad((u_longlong_t
)file_stat
->st_size
);
707 file_stat_entry
->links
= file_stat
->st_nlink
;
709 node_entry
->stats
.stats_len
= 1;
710 node_entry
->stats
.stats_val
= file_stat_entry
;
711 node_entry
->node
= long_long_to_quad((u_longlong_t
)node
);
712 node_entry
->fh_info
= long_long_to_quad(fh_info
);
714 session
->ns_fh_v3
.fh_node_index
++;
721 * ************************************************************************
723 * ************************************************************************
730 * Callback function for file history path information
733 ndmpd_fhpath_v3_cb(lbr_fhlog_call_backs_t
*cbp
, char *path
, struct stat64
*stp
,
737 ndmp_lbr_params_t
*nlp
;
738 ndmpd_module_params_t
*params
;
742 NDMP_LOG(LOG_DEBUG
, "cbp is NULL");
743 } else if (!cbp
->fh_cookie
) {
745 NDMP_LOG(LOG_DEBUG
, "cookie is NULL");
748 NDMP_LOG(LOG_DEBUG
, "path is NULL");
749 } else if (!(nlp
= ndmp_get_nlp(cbp
->fh_cookie
))) {
751 NDMP_LOG(LOG_DEBUG
, "nlp is NULL");
758 NDMP_LOG(LOG_DEBUG
, "pname(%s)", path
);
761 if (NLP_ISSET(nlp
, NLPF_FH
)) {
762 if (!NLP_ISSET(nlp
, NLPF_DIRECT
)) {
763 NDMP_LOG(LOG_DEBUG
, "DAR NOT SET!");
767 params
= get_params(cbp
->fh_cookie
);
768 if (!params
|| !params
->mp_file_history_path_func
) {
772 ndmp_get_relative_path(get_backup_path_v3(params
),
774 if ((err
= ndmpd_api_file_history_file_v3(cbp
->
775 fh_cookie
, p
, stp
, off
)) < 0)
776 NDMP_LOG(LOG_DEBUG
, "\"%s\" %d", path
, err
);
787 * Callback function for file history dir information
790 ndmpd_fhdir_v3_cb(lbr_fhlog_call_backs_t
*cbp
, char *dir
, struct stat64
*stp
)
797 ndmp_lbr_params_t
*nlp
;
798 ndmpd_module_params_t
*params
;
800 char dirpath
[PATH_MAX
];
804 NDMP_LOG(LOG_DEBUG
, "cbp is NULL");
805 } else if (!cbp
->fh_cookie
) {
807 NDMP_LOG(LOG_DEBUG
, "cookie is NULL");
810 NDMP_LOG(LOG_DEBUG
, "dir is NULL");
811 } else if (!(nlp
= ndmp_get_nlp(cbp
->fh_cookie
))) {
813 NDMP_LOG(LOG_DEBUG
, "nlp is NULL");
820 NDMP_LOG(LOG_DEBUG
, "d(%s)", dir
);
822 if (!NLP_ISSET(nlp
, NLPF_FH
))
826 * Veritas net_backup accepts only 2 as the inode number of the backup
827 * root directory. The other way compares the path against the
828 * backup path which is slower.
830 if (stp
->st_ino
== nlp
->nlp_bkdirino
)
836 * There is nothing below this directory to be backed up.
837 * If there was, the bit for this directory would have
838 * been set. Backup root directory is exception. We
839 * always send the dir file history records of it.
841 if (pino
!= ROOT_INODE
&&
842 !dbm_getone(nlp
->nlp_bkmap
, (u_longlong_t
)stp
->st_ino
)) {
843 NDMP_LOG(LOG_DEBUG
, "nothing below here");
847 params
= nlp
->nlp_params
;
848 if (!params
|| !params
->mp_file_history_dir_func
)
860 err
= dp_readdir(dirp
, &pos
, nm
, &nml
, &ino
);
863 "%d reading pos %u dir \"%s\"", err
, pos
, dir
);
870 if (pino
== ROOT_INODE
) {
871 if (rootfs_dot_or_dotdot(nm
))
873 } else if (ino
== nlp
->nlp_bkdirino
&& IS_DOTDOT(nm
)) {
874 NDMP_LOG(LOG_DEBUG
, "nm(%s): %lu", nm
, ino
);
878 if (!dbm_getone(nlp
->nlp_bkmap
, (u_longlong_t
)ino
))
882 * If the entry is on exclusion list dont send the info
884 if (tlm_is_excluded(dir
, nm
, ndmp_excl_list
)) {
886 "name \"%s\" skipped", nm
== 0 ? "nil" : nm
);
890 err
= (*params
->mp_file_history_dir_func
)(cbp
->fh_cookie
, nm
,
893 NDMP_LOG(LOG_DEBUG
, "\"%s\": %d", dir
, err
);
898 * This is a requirement by some DMA's (net_vault) that during
899 * the incremental backup, the node info should also be sent
900 * along with the dir info for all directories leading to a
904 struct stat64 ret_attr
;
906 (void) strlcpy(dirpath
, dir
, PATH_MAX
);
907 (void) strlcat(dirpath
, "/", PATH_MAX
);
908 (void) strlcat(dirpath
, nm
, PATH_MAX
);
909 err
= stat64(dirpath
, &ret_attr
);
912 "Error looking up %s", nm
);
916 if (S_ISDIR(ret_attr
.st_mode
)) {
917 err
= (*params
->mp_file_history_node_func
)(cbp
->
918 fh_cookie
, ino
, &ret_attr
, 0);
920 NDMP_LOG(LOG_DEBUG
, "\"%s/\": %d",
928 (void) closedir(dirp
);
936 * Callback function for file history node information
939 ndmpd_fhnode_v3_cb(lbr_fhlog_call_backs_t
*cbp
, char *dir
, char *file
,
940 struct stat64
*stp
, u_longlong_t off
)
944 ndmp_lbr_params_t
*nlp
;
945 ndmpd_module_params_t
*params
;
949 NDMP_LOG(LOG_DEBUG
, "cbp is NULL");
950 } else if (!cbp
->fh_cookie
) {
952 NDMP_LOG(LOG_DEBUG
, "cookie is NULL");
955 NDMP_LOG(LOG_DEBUG
, "dir is NULL");
958 NDMP_LOG(LOG_DEBUG
, "file is NULL");
961 NDMP_LOG(LOG_DEBUG
, "stp is NULL");
962 } else if (!(nlp
= ndmp_get_nlp(cbp
->fh_cookie
))) {
964 NDMP_LOG(LOG_DEBUG
, "nlp is NULL");
972 NDMP_LOG(LOG_DEBUG
, "d(%s), f(%s)", dir
, file
);
975 if (NLP_ISSET(nlp
, NLPF_FH
)) {
976 if (!NLP_ISSET(nlp
, NLPF_DIRECT
))
978 if (stp
->st_ino
== nlp
->nlp_bkdirino
) {
981 "bkroot %d -> %d", stp
->st_ino
, ROOT_INODE
);
985 params
= nlp
->nlp_params
;
986 if (!params
|| !params
->mp_file_history_node_func
)
988 else if ((err
= (*params
->mp_file_history_node_func
)(cbp
->
989 fh_cookie
, ino
, stp
, off
)) < 0)
990 NDMP_LOG(LOG_DEBUG
, "\"%s/%s\" %d", dir
, file
, err
);
998 * ndmp_send_recovery_stat_v3
1000 * Send the recovery status to the DMA
1003 ndmp_send_recovery_stat_v3(ndmpd_module_params_t
*params
,
1004 ndmp_lbr_params_t
*nlp
, int idx
, int stat
)
1007 mem_ndmp_name_v3_t
*ep
;
1011 NDMP_LOG(LOG_DEBUG
, "params == NULL");
1012 } else if (!params
->mp_file_recovered_func
) {
1013 NDMP_LOG(LOG_DEBUG
, "paramsfile_recovered_func == NULL");
1015 NDMP_LOG(LOG_DEBUG
, "nlp == NULL");
1016 } else if (idx
< 0) {
1017 NDMP_LOG(LOG_DEBUG
, "idx(%d) < 0", idx
);
1018 } else if (!(ep
= (mem_ndmp_name_v3_t
*)MOD_GETNAME(params
, idx
))) {
1019 NDMP_LOG(LOG_DEBUG
, "nlist[%d] == NULL", idx
);
1020 } else if (!ep
->nm3_opath
) {
1021 NDMP_LOG(LOG_DEBUG
, "nlist[%d].nm3_opath == NULL", idx
);
1024 "ep[%d].nm3_opath \"%s\"", idx
, ep
->nm3_opath
);
1025 rv
= MOD_FILERECOVERD(params
, ep
->nm3_opath
, stat
);
1033 * ndmpd_path_restored_v3
1035 * Send the recovery status and the information for the restored
1040 ndmpd_path_restored_v3(lbr_fhlog_call_backs_t
*cbp
, char *name
,
1041 struct stat64
*st
, u_longlong_t ll_idx
)
1044 ndmp_lbr_params_t
*nlp
;
1045 ndmpd_module_params_t
*params
;
1046 int idx
= (int)ll_idx
;
1049 NDMP_LOG(LOG_DEBUG
, "cbp is NULL");
1053 NDMP_LOG(LOG_DEBUG
, "name is NULL");
1057 NDMP_LOG(LOG_DEBUG
, "name: \"%s\", idx: %d", name
, idx
);
1059 nlp
= ndmp_get_nlp(cbp
->fh_cookie
);
1061 NDMP_LOG(LOG_DEBUG
, "nlp is NULL");
1064 if (idx
< 0 || idx
>= nlp
->nlp_nfiles
) {
1065 NDMP_LOG(LOG_DEBUG
, "Invalid idx: %d", idx
);
1068 params
= nlp
->nlp_params
;
1069 if (!params
|| !params
->mp_file_recovered_func
)
1072 if (nlp
->nlp_lastidx
== -1)
1073 nlp
->nlp_lastidx
= idx
;
1076 (void) bm_setone(nlp
->nlp_rsbm
, (u_longlong_t
)idx
);
1078 * Note: We should set the nm3_err here.
1080 if (nlp
->nlp_lastidx
!= idx
) {
1081 rv
= ndmp_send_recovery_stat_v3(params
, nlp
, nlp
->nlp_lastidx
,
1083 nlp
->nlp_lastidx
= idx
;
1092 * ndmpd_file_history_init
1094 * Initialize file history variables.
1095 * Note that the entry and name buffers are not allocated here.
1096 * Since it is not know if the backup module will be sending file history
1097 * data or what kind of data (path or dir/node), the entry and name
1098 * buffers are not allocated until the first call to one of the file history
1099 * entry functions is made. This way resources are only allocated as
1103 * session (input) - session pointer.
1109 ndmpd_file_history_init(ndmpd_session_t
*session
)
1111 session
->ns_fh
.fh_path_entries
= 0;
1112 session
->ns_fh
.fh_dir_entries
= 0;
1113 session
->ns_fh
.fh_node_entries
= 0;
1114 session
->ns_fh
.fh_path_name_buf
= 0;
1115 session
->ns_fh
.fh_dir_name_buf
= 0;
1116 session
->ns_fh
.fh_path_index
= 0;
1117 session
->ns_fh
.fh_dir_index
= 0;
1118 session
->ns_fh
.fh_node_index
= 0;
1119 session
->ns_fh
.fh_path_name_buf_index
= 0;
1120 session
->ns_fh
.fh_dir_name_buf_index
= 0;
1125 session
->ns_fh_v3
.fh_files
= 0;
1126 session
->ns_fh_v3
.fh_dirs
= 0;
1127 session
->ns_fh_v3
.fh_nodes
= 0;
1128 session
->ns_fh_v3
.fh_file_names
= 0;
1129 session
->ns_fh_v3
.fh_dir_names
= 0;
1130 session
->ns_fh_v3
.fh_file_stats
= 0;
1131 session
->ns_fh_v3
.fh_node_stats
= 0;
1132 session
->ns_fh_v3
.fh_file_name_buf
= 0;
1133 session
->ns_fh_v3
.fh_dir_name_buf
= 0;
1134 session
->ns_fh_v3
.fh_file_index
= 0;
1135 session
->ns_fh_v3
.fh_dir_index
= 0;
1136 session
->ns_fh_v3
.fh_node_index
= 0;
1137 session
->ns_fh_v3
.fh_file_name_buf_index
= 0;
1138 session
->ns_fh_v3
.fh_dir_name_buf_index
= 0;
1143 * ndmpd_file_history_cleanup_v2
1145 * Send (or discard) any buffered file history entries.
1148 * session (input) - session pointer.
1149 * send_flag (input) - if TRUE buffered entries are sent.
1150 * if FALSE buffered entries are discarded.
1156 ndmpd_file_history_cleanup_v2(ndmpd_session_t
*session
, boolean_t send_flag
)
1158 if (send_flag
== TRUE
) {
1159 (void) ndmpd_api_file_history_path_v2(session
, 0, 0, 0);
1160 (void) ndmpd_api_file_history_dir_v2(session
, 0, 0, 0);
1161 (void) ndmpd_api_file_history_node_v2(session
, 0, 0, 0);
1164 if (session
->ns_fh
.fh_path_entries
!= 0) {
1165 free(session
->ns_fh
.fh_path_entries
);
1166 session
->ns_fh
.fh_path_entries
= 0;
1168 if (session
->ns_fh
.fh_dir_entries
!= 0) {
1169 free(session
->ns_fh
.fh_dir_entries
);
1170 session
->ns_fh
.fh_dir_entries
= 0;
1172 if (session
->ns_fh
.fh_node_entries
!= 0) {
1173 free(session
->ns_fh
.fh_node_entries
);
1174 session
->ns_fh
.fh_node_entries
= 0;
1176 if (session
->ns_fh
.fh_path_name_buf
!= 0) {
1177 free(session
->ns_fh
.fh_path_name_buf
);
1178 session
->ns_fh
.fh_path_name_buf
= 0;
1180 if (session
->ns_fh
.fh_dir_name_buf
!= 0) {
1181 free(session
->ns_fh
.fh_dir_name_buf
);
1182 session
->ns_fh
.fh_dir_name_buf
= 0;
1184 session
->ns_fh
.fh_path_index
= 0;
1185 session
->ns_fh
.fh_dir_index
= 0;
1186 session
->ns_fh
.fh_node_index
= 0;
1187 session
->ns_fh
.fh_path_name_buf_index
= 0;
1188 session
->ns_fh
.fh_dir_name_buf_index
= 0;
1193 * ndmpd_file_history_cleanup_v3
1195 * Send (or discard) any buffered file history entries.
1198 * session (input) - session pointer.
1199 * send_flag (input) - if TRUE buffered entries are sent.
1200 * if FALSE buffered entries are discarded.
1206 ndmpd_file_history_cleanup_v3(ndmpd_session_t
*session
, boolean_t send_flag
)
1208 if (send_flag
== TRUE
) {
1209 (void) ndmpd_api_file_history_file_v3(session
, 0, 0, 0);
1210 (void) ndmpd_api_file_history_dir_v3(session
, 0, 0, 0);
1211 (void) ndmpd_api_file_history_node_v3(session
, 0, 0, 0);
1214 if (session
->ns_fh_v3
.fh_files
!= 0) {
1215 free(session
->ns_fh_v3
.fh_files
);
1216 session
->ns_fh_v3
.fh_files
= 0;
1218 if (session
->ns_fh_v3
.fh_dirs
!= 0) {
1219 free(session
->ns_fh_v3
.fh_dirs
);
1220 session
->ns_fh_v3
.fh_dirs
= 0;
1222 if (session
->ns_fh_v3
.fh_nodes
!= 0) {
1223 free(session
->ns_fh_v3
.fh_nodes
);
1224 session
->ns_fh_v3
.fh_nodes
= 0;
1226 if (session
->ns_fh_v3
.fh_file_names
!= 0) {
1227 free(session
->ns_fh_v3
.fh_file_names
);
1228 session
->ns_fh_v3
.fh_file_names
= 0;
1230 if (session
->ns_fh_v3
.fh_dir_names
!= 0) {
1231 free(session
->ns_fh_v3
.fh_dir_names
);
1232 session
->ns_fh_v3
.fh_dir_names
= 0;
1234 if (session
->ns_fh_v3
.fh_file_stats
!= 0) {
1235 free(session
->ns_fh_v3
.fh_file_stats
);
1236 session
->ns_fh_v3
.fh_file_stats
= 0;
1238 if (session
->ns_fh_v3
.fh_node_stats
!= 0) {
1239 free(session
->ns_fh_v3
.fh_node_stats
);
1240 session
->ns_fh_v3
.fh_node_stats
= 0;
1242 if (session
->ns_fh_v3
.fh_file_name_buf
!= 0) {
1243 free(session
->ns_fh_v3
.fh_file_name_buf
);
1244 session
->ns_fh_v3
.fh_file_name_buf
= 0;
1246 if (session
->ns_fh_v3
.fh_dir_name_buf
!= 0) {
1247 free(session
->ns_fh_v3
.fh_dir_name_buf
);
1248 session
->ns_fh_v3
.fh_dir_name_buf
= 0;
1251 session
->ns_fh_v3
.fh_file_index
= 0;
1252 session
->ns_fh_v3
.fh_dir_index
= 0;
1253 session
->ns_fh_v3
.fh_node_index
= 0;
1254 session
->ns_fh_v3
.fh_file_name_buf_index
= 0;
1255 session
->ns_fh_v3
.fh_dir_name_buf_index
= 0;
1260 * ndmpd_file_history_cleanup
1262 * Send any pending posts and clean up
1265 ndmpd_file_history_cleanup(ndmpd_session_t
*session
, boolean_t send_flag
)
1267 switch (session
->ns_protocol_version
) {
1270 ndmpd_file_history_cleanup_v2(session
, send_flag
);
1274 ndmpd_file_history_cleanup_v3(session
, send_flag
);
1277 NDMP_LOG(LOG_DEBUG
, "Unknown version %d",
1278 session
->ns_protocol_version
);
1285 * Callbacks from LBR.
1287 static ndmpd_module_params_t
*
1288 get_params(void *cookie
)
1290 ndmp_lbr_params_t
*nlp
;
1292 if ((nlp
= ndmp_get_nlp(cookie
)) == NULL
)
1295 return (nlp
->nlp_params
);
1302 * Check in LB parameters if file history is requested
1305 fh_requested(void *cookie
)
1307 ndmp_lbr_params_t
*nlp
;
1309 if ((nlp
= ndmp_get_nlp(cookie
)) == NULL
) {
1310 NDMP_LOG(LOG_DEBUG
, "nlp is NULL");
1314 NDMP_LOG(LOG_DEBUG
, "nlp_fh %c", NDMP_YORN(NLP_ISSET(nlp
, NLPF_FH
)));
1316 return (NLP_ISSET(nlp
, NLPF_FH
));
1321 * ndmpd_file_history_path
1323 * Generates file history path information posts
1326 * Action must be determined when the 'dir' and/or 'file'
1327 * arguments of ndmpd_file_history_path(), ndmpd_file_history_dir(), and
1328 * ndmpd_file_history_node() are NULL.
1332 ndmpd_file_history_path(lbr_fhlog_call_backs_t
*cbp
, char *path
,
1333 struct stat64
*stp
, u_longlong_t off
)
1336 ndmpd_module_params_t
*params
;
1340 NDMP_LOG(LOG_DEBUG
, "cbp is NULL");
1341 } else if (!cbp
->fh_cookie
) {
1343 NDMP_LOG(LOG_DEBUG
, "cookie is NULL");
1346 NDMP_LOG(LOG_DEBUG
, "path is NULL");
1349 NDMP_LOG(LOG_DEBUG
, "stp is NULL");
1356 NDMP_LOG(LOG_DEBUG
, "path: \"%s\"", path
);
1359 if (fh_requested(cbp
->fh_cookie
)) {
1360 params
= get_params(cbp
->fh_cookie
);
1361 if (params
== NULL
|| params
->mp_file_history_path_func
== NULL
)
1363 else if ((err
= (*params
->mp_file_history_path_func
)(cbp
->
1364 fh_cookie
, path
, stp
, 0)) < 0)
1365 NDMP_LOG(LOG_DEBUG
, "\"%s\": %d", path
, err
);
1373 * ndmpd_file_history_dir
1375 * Generate file history directory information posts
1378 ndmpd_file_history_dir(lbr_fhlog_call_backs_t
*cbp
, char *dir
,
1381 char nm
[PATH_MAX
+1];
1386 ndmp_lbr_params_t
*nlp
;
1387 ndmpd_module_params_t
*params
;
1389 char dirpath
[PATH_MAX
];
1393 NDMP_LOG(LOG_DEBUG
, "cbp is NULL");
1394 } else if (!cbp
->fh_cookie
) {
1396 NDMP_LOG(LOG_DEBUG
, "cookie is NULL");
1399 NDMP_LOG(LOG_DEBUG
, "dir is NULL");
1402 NDMP_LOG(LOG_DEBUG
, "stp is NULL");
1403 } if (!(nlp
= ndmp_get_nlp(cbp
->fh_cookie
))) {
1405 NDMP_LOG(LOG_DEBUG
, "nlp is NULL");
1412 NDMP_LOG(LOG_DEBUG
, "dir: \"%s\"", dir
);
1414 if (!fh_requested(cbp
->fh_cookie
))
1418 * Veritas net_backup accepts only 2 as the inode number of the backup
1419 * root directory. The other way compares the path against the
1420 * backup path which is slower.
1422 if (stp
->st_ino
== nlp
->nlp_bkdirino
)
1428 * There is nothing below this directory to be backed up.
1429 * If there was, the bit for this directory would have
1430 * been set. Backup root directory is exception. We
1431 * always send the dir file history records of it.
1433 if (pino
!= ROOT_INODE
&&
1434 !dbm_getone(nlp
->nlp_bkmap
, (u_longlong_t
)stp
->st_ino
)) {
1435 NDMP_LOG(LOG_DEBUG
, "nothing below here");
1439 params
= get_params(cbp
->fh_cookie
);
1440 if (params
== NULL
|| params
->mp_file_history_dir_func
== NULL
) {
1447 dirp
= opendir(dir
);
1453 err
= dp_readdir(dirp
, &pos
, nm
, &nml
, &ino
);
1456 "%d reading pos %u dir \"%s\"", err
, pos
, dir
);
1463 if (pino
== ROOT_INODE
) {
1464 if (rootfs_dot_or_dotdot(nm
))
1466 } else if (ino
== nlp
->nlp_bkdirino
&& IS_DOTDOT(nm
)) {
1467 NDMP_LOG(LOG_DEBUG
, "nm(%s): %lu", nm
, ino
);
1471 if (!dbm_getone(nlp
->nlp_bkmap
, (u_longlong_t
)ino
))
1474 err
= (*params
->mp_file_history_dir_func
)(cbp
->fh_cookie
, nm
,
1477 NDMP_LOG(LOG_DEBUG
, "\"%s/%s\": %d", dir
, nm
, err
);
1482 * This is a requirement by some DMA's (net_vault) that during
1483 * the incremental backup, the node info should also be sent
1484 * along with the dir info for all directories leading to a
1488 struct stat64 ret_attr
;
1490 (void) strlcpy(dirpath
, dir
, PATH_MAX
);
1491 (void) strlcat(dirpath
, "/", PATH_MAX
);
1492 (void) strlcat(dirpath
, nm
, PATH_MAX
);
1493 err
= stat64(dirpath
, &ret_attr
);
1496 "Error looking up %s", nm
);
1500 if (S_ISDIR(ret_attr
.st_mode
)) {
1501 err
= (*params
->mp_file_history_node_func
)(cbp
->
1502 fh_cookie
, ino
, &ret_attr
, 0);
1504 NDMP_LOG(LOG_DEBUG
, "\"%s/\": %d",
1512 (void) closedir(dirp
);
1518 * ndmpd_file_history_node
1520 * Generate file history node information posts
1524 ndmpd_file_history_node(lbr_fhlog_call_backs_t
*cbp
, char *dir
, char *file
,
1525 struct stat64
*stp
, u_longlong_t off
)
1529 ndmp_lbr_params_t
*nlp
;
1530 ndmpd_module_params_t
*params
;
1534 NDMP_LOG(LOG_DEBUG
, "cbp is NULL");
1535 } else if (!cbp
->fh_cookie
) {
1537 NDMP_LOG(LOG_DEBUG
, "cookie is NULL");
1540 NDMP_LOG(LOG_DEBUG
, "dir is NULL");
1543 NDMP_LOG(LOG_DEBUG
, "file is NULL");
1546 NDMP_LOG(LOG_DEBUG
, "stp is NULL");
1547 } else if (!(nlp
= ndmp_get_nlp(cbp
->fh_cookie
))) {
1549 NDMP_LOG(LOG_DEBUG
, "nlp is NULL");
1556 NDMP_LOG(LOG_DEBUG
, "d(%s), f(%s)", dir
, file
);
1559 if (fh_requested(cbp
->fh_cookie
) == TRUE
) {
1560 if (stp
->st_ino
== nlp
->nlp_bkdirino
) {
1563 "bkroot %d -> %d", stp
->st_ino
, ROOT_INODE
);
1568 params
= get_params(cbp
->fh_cookie
);
1569 if (params
== NULL
|| params
->mp_file_history_node_func
== NULL
)
1571 else if ((err
= (*params
->mp_file_history_node_func
)(cbp
->
1572 fh_cookie
, ino
, stp
, 0)) < 0)
1573 NDMP_LOG(LOG_DEBUG
, "\"%s/\": %d", dir
, file
, err
);
1582 * ndmpd_path_restored
1584 * Mark the specified path as a restored path
1588 ndmpd_path_restored(lbr_fhlog_call_backs_t
*cbp
, char *name
, struct stat64
*stp
,
1589 u_longlong_t ll_pos
)
1593 ndmp_lbr_params_t
*nlp
;
1594 ndmpd_module_params_t
*params
;
1595 int pos
= (int)ll_pos
;
1598 NDMP_LOG(LOG_DEBUG
, "cbp is NULL");
1602 NDMP_LOG(LOG_DEBUG
, "name is NULL");
1606 NDMP_LOG(LOG_DEBUG
, "name: \"%s\", pos: %d",
1609 if ((nlp
= ndmp_get_nlp(cbp
->fh_cookie
)) == NULL
) {
1610 NDMP_LOG(LOG_DEBUG
, "nlp is NULL");
1613 if (pos
< 0 || pos
>= nlp
->nlp_nfiles
) {
1614 NDMP_LOG(LOG_DEBUG
, "Invalid pos: %d", pos
);
1617 params
= get_params(cbp
->fh_cookie
);
1618 if (params
== NULL
|| params
->mp_file_recovered_func
== NULL
)
1622 if (!nlp
->nlp_restored
[pos
]) {
1623 entp
= (ndmp_name
*)MOD_GETNAME(params
, pos
);
1624 if (entp
&& entp
->name
)
1627 if ((rv
= MOD_FILERECOVERD(params
, name
, 0)) >= 0)
1628 nlp
->nlp_restored
[pos
] = TRUE
;
1638 * Reads the entry of the directory and provides other information
1639 * such as i-number, name, length and saves the dir entry position
1640 * in a cookie for future calls.
1643 dp_readdir(DIR *dirp
, unsigned long *cookiep
, char *name
, int *n_namep
,
1644 unsigned long *fileidp
)
1646 struct dirent
*entp
;
1649 if ((entp
= readdir(dirp
)) == 0) {
1657 *fileidp
= entp
->d_ino
;
1658 (void) strlcpy(name
, entp
->d_name
, *n_namep
);
1659 *n_namep
= entp
->d_reclen
+ 1;
1660 *cookiep
= telldir(dirp
);