| /* |
| * Copyright (c) 2000-2001 Silicon Graphics, Inc. |
| * All Rights Reserved. |
| * |
| * This program is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU General Public License as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it would be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <xfs/xfs.h> |
| #include <xfs/jdm.h> |
| |
| #include <sys/file.h> |
| #include <sys/stat.h> |
| #include <time.h> |
| #include <fcntl.h> |
| #include <errno.h> |
| #include <sys/dir.h> |
| #include "types.h" |
| #include "inv_priv.h" |
| |
| |
| |
| /*----------------------------------------------------------------------*/ |
| /* get_counters, get_headers, get_invtrecord, put_invtrecord, ... */ |
| /* */ |
| /* These implement low level routines that take care of disk I/Os. */ |
| /* In most cases, the caller has the option of locking before calling */ |
| /* the routine. */ |
| /* */ |
| /*----------------------------------------------------------------------*/ |
| |
| intgen_t |
| get_counters( int fd, void **cntpp, size_t cntsz ) |
| { |
| /* object must be locked at least SHARED by caller */ |
| u_int num; |
| ASSERT( cntsz >= sizeof( invt_counter_t ) ); |
| |
| *cntpp = calloc( 1, cntsz); |
| |
| /* find the number of sessions and the max possible */ |
| if ( GET_REC_NOLOCK( fd, (void *) *cntpp, cntsz, (off64_t) 0 ) < 0 ) { |
| free( *cntpp ); |
| *cntpp = NULL; |
| return -1; |
| } |
| |
| num = ((invt_counter_t *)(*cntpp))->ic_curnum; |
| |
| if ( ( (invt_counter_t *)(*cntpp))->ic_vernum != INV_VERSION ) { |
| mlog( MLOG_NORMAL | MLOG_INV, _( |
| "INV : Unknown version %d - Expected version %d\n"), |
| (int) ( (invt_counter_t *)(*cntpp))->ic_vernum, |
| (int) INV_VERSION ); |
| ASSERT ( ((invt_counter_t *)(*cntpp))->ic_vernum == |
| INV_VERSION ); |
| } |
| |
| return (intgen_t) num; |
| } |
| |
| |
| |
| |
| |
| /*----------------------------------------------------------------------*/ |
| /* get_headers */ |
| /*----------------------------------------------------------------------*/ |
| |
| intgen_t |
| get_headers( int fd, void **hdrs, size_t bufsz, size_t off ) |
| { |
| |
| *hdrs = malloc( bufsz ); |
| if ( *hdrs == NULL ) { |
| INV_PERROR( _("get_headers() - malloc(seshdrs)\n") ); |
| return -1; |
| } |
| /* file must be locked at least SHARED by caller */ |
| |
| /* get the array of hdrs */ |
| if ( GET_REC_NOLOCK( fd, (void *) *hdrs, bufsz, (off64_t)off ) < 0 ) { |
| free ( *hdrs ); |
| *hdrs = NULL; |
| return -1; |
| } |
| |
| return 1; |
| } |
| |
| |
| |
| /*----------------------------------------------------------------------*/ |
| /* get_invtrecord */ |
| /*----------------------------------------------------------------------*/ |
| |
| intgen_t |
| get_invtrecord( int fd, void *buf, size_t bufsz, off64_t off, |
| int whence, bool_t dolock ) |
| { |
| int nread; |
| |
| ASSERT ( fd >= 0 ); |
| |
| if ( dolock ) |
| INVLOCK( fd, LOCK_SH ); |
| |
| if ( lseek( fd, (off_t)off, whence ) < 0 ) { |
| INV_PERROR( _("Error in reading inventory record " |
| "(lseek failed): ") ); |
| if ( dolock ) |
| INVLOCK( fd, LOCK_UN ); |
| return -1; |
| } |
| |
| nread = read( fd, buf, bufsz ); |
| |
| if ( nread != (int) bufsz ) { |
| INV_PERROR( _("Error in reading inventory record :") ); |
| if ( dolock ) |
| INVLOCK( fd, LOCK_UN ); |
| return -1; |
| } |
| |
| if ( dolock ) |
| INVLOCK( fd, LOCK_UN ); |
| |
| return nread; |
| } |
| |
| |
| |
| |
| |
| |
| /*----------------------------------------------------------------------*/ |
| /* put_invtrecord */ |
| /*----------------------------------------------------------------------*/ |
| |
| intgen_t |
| put_invtrecord( int fd, void *buf, size_t bufsz, off64_t off, |
| int whence, bool_t dolock ) |
| { |
| int nwritten; |
| |
| if ( dolock ) |
| INVLOCK( fd, LOCK_EX ); |
| |
| if ( lseek( fd, (off_t)off, whence ) < 0 ) { |
| INV_PERROR( _("Error in writing inventory record " |
| "(lseek failed): ") ); |
| if ( dolock ) |
| INVLOCK( fd, LOCK_UN ); |
| return -1; |
| } |
| |
| if (( nwritten = write( fd, buf, bufsz ) ) != (int) bufsz ) { |
| INV_PERROR( _("Error in writing inventory record :") ); |
| if ( dolock ) |
| INVLOCK( fd, LOCK_UN ); |
| return -1; |
| } |
| |
| if ( dolock ) |
| INVLOCK( fd, LOCK_UN ); |
| return nwritten; |
| } |
| |
| |
| |
| |
| |
| |
| |
| /*----------------------------------------------------------------------*/ |
| /* get_headerinfo */ |
| /*----------------------------------------------------------------------*/ |
| |
| |
| intgen_t |
| get_headerinfo( int fd, void **hdrs, void **cnt, |
| size_t hdrsz, size_t cntsz, bool_t dolock ) |
| { |
| int num; |
| |
| /* get a lock on the table for reading */ |
| if ( dolock ) INVLOCK( fd, LOCK_SH ); |
| |
| num = get_counters( fd, cnt, cntsz ); |
| |
| /* If there are no sessions recorded yet, we're done too */ |
| if ( num > 0 ) { |
| if ( get_headers( fd, hdrs, hdrsz * (size_t)num, cntsz ) < 0 ) { |
| free ( *cnt ); |
| num = -1; |
| } |
| } |
| |
| if ( dolock ) INVLOCK( fd, LOCK_UN ); |
| return num; |
| } |
| |
| |
| |
| /*----------------------------------------------------------------------*/ |
| /* get_lastheader */ |
| /*----------------------------------------------------------------------*/ |
| |
| intgen_t |
| get_lastheader( int fd, void **ent, size_t hdrsz, size_t cntsz ) |
| { |
| int nindices; |
| void *arr = NULL; |
| invt_counter_t *cnt = NULL; |
| char *pos; |
| /* get the entries in the inv_index */ |
| if ( ( nindices = GET_ALLHDRS_N_CNTS( fd, &arr, (void **)&cnt, |
| hdrsz, cntsz )) <= 0 ) { |
| return -1; |
| } |
| |
| /* if there's space anywhere at all, then it must be in the last |
| entry */ |
| *ent = malloc( hdrsz ); |
| pos = (char *) arr + ( (u_int)nindices - 1 ) * hdrsz; |
| memcpy( *ent, pos, hdrsz ); |
| free ( arr ); |
| free ( cnt ); |
| |
| return nindices; |
| } |
| |
| |