| /* |
| * Copyright (c) 2002 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 <signal.h> |
| #include <ncurses.h> |
| #include <sys/mman.h> |
| |
| #include "types.h" |
| #include "mlog.h" |
| #include "inv_priv.h" |
| #include "getopt.h" |
| |
| #include "invutil.h" |
| #include "cmenu.h" |
| #include "list.h" |
| #include "invidx.h" |
| #include "fstab.h" |
| |
| fstab_fileinfo_t *fstab_file; |
| int fstab_numfiles; |
| |
| menu_ops_t fstab_ops = { |
| NULL, |
| NULL, |
| NULL, /*fstab_saveall,*/ |
| fstab_select, |
| NULL, |
| NULL, |
| NULL, |
| NULL, |
| fstab_highlight, |
| menu_unhighlight, |
| fstab_commit, |
| fstab_prune, |
| }; |
| |
| /*ARGSUSED*/ |
| int |
| fstab_commit(WINDOW *win, node_t *current, node_t *list) |
| { |
| int i; |
| int fidx; |
| node_t *n; |
| data_t *d; |
| invt_fstab_t *fstabentry; |
| int fstabentry_idx; |
| |
| n = current; |
| if(n == NULL || n->data == NULL) |
| return 0; |
| |
| d = ((data_t *)(n->data)); |
| fidx = d->file_idx; |
| fstabentry = fstab_file[fidx].data[d->data_idx]; |
| |
| if(d->deleted == BOOL_TRUE && d->imported == BOOL_FALSE) { |
| for(i = 0; i < d->nbr_children; i++) { |
| invidx_commit(win, d->children[i], list); |
| } |
| mark_all_children_commited(current); |
| |
| fstabentry_idx = (int)(((long)fstabentry - (long)fstab_file[fidx].mapaddr - sizeof(invt_counter_t)) / sizeof(invt_fstab_t)); |
| |
| if ( fstab_file[fidx].counter->ic_curnum > 1 ) { |
| memmove(fstabentry, |
| fstabentry + 1, |
| (sizeof(invt_fstab_t) * (fstab_file[fidx].counter->ic_curnum - fstabentry_idx - 1))); |
| |
| fstab_file[fidx].data[d->data_idx] = NULL; |
| |
| for(i = d->data_idx + 1; i < fstab_file[fidx].numrecords; i++) { |
| if(fstab_file[fidx].data[i] != NULL) |
| fstab_file[fidx].data[i]--; |
| } |
| } |
| fstab_file[fidx].counter->ic_curnum--; |
| } |
| else if(d->imported == BOOL_TRUE) { |
| invt_fstab_t *dest; |
| |
| for(i = 0; i < d->nbr_children; i++) { |
| invidx_commit(win, d->children[i], list); |
| } |
| mark_all_children_commited(current); |
| |
| if(find_matching_fstab(0, fstabentry) >= 0) { |
| return 0; |
| } |
| |
| if(fstab_file[0].counter->ic_curnum < fstab_file[0].nEntries) { |
| dest = fstab_file[0].data[fstab_file[0].counter->ic_curnum - 1] + 1; |
| } |
| else { |
| /* expand mmap by one */ |
| dest = remmap_fstab(0, 1); |
| } |
| |
| /* copy new data to mmap */ |
| memmove(dest, fstabentry, sizeof(*fstabentry)); |
| |
| /* increment counter */ |
| fstab_file[0].counter->ic_curnum++; |
| } |
| |
| return 0; |
| } |
| |
| /*ARGSUSED*/ |
| int |
| fstab_select(WINDOW *win, node_t *current, node_t *list) |
| { |
| data_t *d; |
| |
| if(current == NULL || current->data == NULL) { |
| return 0; |
| } |
| d = (data_t *)(current->data); |
| |
| if(d->expanded == TRUE) { |
| return menu_collapse(win, current, list); |
| } |
| |
| return menu_expand(win, current, list); |
| } |
| |
| /*ARGSUSED*/ |
| int |
| fstab_highlight(WINDOW *win, node_t *current, node_t *list) |
| { |
| static char txt[256]; |
| char uuidstr[UUID_STR_LEN + 1]; |
| data_t *d; |
| invt_fstab_t *fstabentry; |
| |
| if(current == NULL || current->data == NULL) { |
| return 0; |
| } |
| d = (data_t *)(current->data); |
| fstabentry = fstab_file[d->file_idx].data[d->data_idx]; |
| |
| wclear(infowin); |
| |
| put_info_header("fstab entry"); |
| |
| snprintf(txt, sizeof(txt), "device: %s", fstabentry->ft_devpath); |
| put_info_line(1, txt); |
| |
| uuid_unparse(fstabentry->ft_uuid, uuidstr); |
| snprintf(txt, sizeof(txt), "uuid: %s", uuidstr); |
| put_info_line(2, txt); |
| |
| return FALSE; |
| } |
| |
| /*ARGSUSED*/ |
| int |
| fstab_prune(char *mountpt, uuid_t *uuidp, time32_t prunetime, node_t *node, node_t *list) |
| { |
| data_t *d; |
| invt_fstab_t *fstabentry; |
| |
| if(node == NULL || node->data == NULL) { |
| return BOOL_FALSE; |
| } |
| |
| d = (data_t *)(node->data); |
| fstabentry = fstab_file[d->file_idx].data[d->data_idx]; |
| |
| if(mountpt != NULL && mntpnt_equal(mountpt, fstabentry->ft_mountpt)) { |
| return BOOL_TRUE; |
| } |
| if((!uuid_is_null(*uuidp)) |
| && (uuid_compare(*uuidp, fstabentry->ft_uuid) == 0)) { |
| return BOOL_TRUE; |
| } |
| |
| return BOOL_FALSE; |
| } |
| |
| int |
| add_fstab_data(int fidx, invt_fstab_t *data) |
| { |
| if(fstab_file[fidx].numrecords == 0) { |
| fstab_file[fidx].data = malloc(sizeof(*fstab_file[fidx].data)); |
| if(fstab_file[fidx].data == NULL) { |
| fprintf(stderr, "%s: internal memory error: fstab data allocation\n", g_programName); |
| exit(1); |
| } |
| } |
| else { |
| fstab_file[fidx].data = realloc(fstab_file[fidx].data, |
| sizeof(*fstab_file[fidx].data) |
| * (fstab_file[fidx].numrecords + 1)); |
| if(fstab_file[fidx].data == NULL) { |
| fprintf(stderr, "%s: internal memory error: fstab data reallocation\n", g_programName); |
| exit(1); |
| } |
| } |
| fstab_file[fidx].data[fstab_file[fidx].numrecords] = data; |
| fstab_file[fidx].numrecords++; |
| |
| return fstab_file[fidx].numrecords - 1; |
| } |
| |
| node_t * |
| generate_fstab_menu(char * inv_path, node_t *startnode, int level, char *fstabname) |
| { |
| int i; |
| char *invname; |
| char *txt; |
| int idx; |
| int len; |
| node_t *list = NULL; |
| node_t *n; |
| invt_fstab_t *fstab_entry; |
| |
| if((idx = open_fstab(fstabname)) < 0) { |
| return NULL; |
| } |
| fstab_entry = (invt_fstab_t *)(fstab_file[idx].mapaddr + sizeof(invt_counter_t)); |
| |
| n = startnode; |
| for(i=0; i < fstab_file[idx].counter->ic_curnum; i++) { |
| len = strlen(fstab_entry[i].ft_mountpt) + strlen(fstab_entry[i].ft_devpath) + 40; |
| txt = malloc(len); |
| if(txt == NULL) { |
| fprintf(stderr, "%s: internal memory error: fstab_text\n", g_programName); |
| exit(1); |
| } |
| snprintf(txt, len, " fs: %s", fstab_entry[i].ft_mountpt); |
| |
| n = list_add(n, node_create(BOOL_FALSE, /* hidden */ |
| BOOL_FALSE, /* expanded */ |
| level, /* level */ |
| BOOL_FALSE, /* deleted */ |
| idx, /* file_idx */ |
| txt, /* text */ |
| &(fstab_ops), /* menu ops */ |
| NULL, /* parent */ |
| NULL, /* children */ |
| 0, /* nbr_children */ |
| i)); /* data_idx */ |
| if(i == 0) { |
| list = n; |
| } |
| if(n == NULL) { |
| fprintf(stderr, "%s: internal memory error: list_add: node_create: fstab\n", g_programName); |
| exit(1); |
| } |
| |
| add_fstab_data(idx, &(fstab_entry[i])); |
| invname = GetNameOfInvIndex(inv_path, fstab_entry[i].ft_uuid); |
| n = generate_invidx_menu(inv_path, n, level + 1, invname); |
| free(invname); |
| } |
| |
| return list; |
| } |
| |
| int |
| add_fstab(char *name, int fd, int nEntries, char *mapaddr, invt_counter_t *counter) |
| { |
| static int highwatermark = 10; |
| |
| if(fstab_numfiles == 0) { |
| fstab_file = malloc(sizeof(*fstab_file) * highwatermark); |
| if(fstab_file == NULL) { |
| fprintf(stderr, "%s: internal memory error: malloc fstab_file\n", g_programName); |
| exit(1); |
| } |
| } |
| else { |
| if(fstab_numfiles >= highwatermark - 1) { |
| highwatermark += highwatermark; |
| |
| fstab_file = realloc(fstab_file, sizeof(*fstab_file) * highwatermark); |
| if(fstab_file == NULL) { |
| fprintf(stderr, "%s: internal memory error: realloc fstab\n", g_programName); |
| exit(1); |
| } |
| } |
| } |
| |
| fstab_file[fstab_numfiles].fd = fd; |
| fstab_file[fstab_numfiles].name = name; |
| fstab_file[fstab_numfiles].nEntries = nEntries; |
| fstab_file[fstab_numfiles].mapaddr = mapaddr; |
| fstab_file[fstab_numfiles].counter = counter; |
| fstab_file[fstab_numfiles].data = NULL; |
| fstab_file[fstab_numfiles].numrecords = 0; |
| |
| fstab_numfiles++; |
| |
| return fstab_numfiles - 1; |
| } |
| |
| int |
| fstab_equal(invt_fstab_t *f1, invt_fstab_t *f2) |
| { |
| if(strcmp(f1->ft_mountpt, f2->ft_mountpt) != 0) |
| return BOOL_FALSE; |
| |
| if(strcmp(f1->ft_devpath, f2->ft_devpath) != 0) |
| return BOOL_FALSE; |
| |
| if(uuid_compare(f1->ft_uuid, f2->ft_uuid) != 0) |
| return BOOL_FALSE; |
| |
| return BOOL_TRUE; |
| } |
| |
| int |
| find_matching_fstab(int fidx, invt_fstab_t *fstabentry) |
| { |
| int i; |
| |
| for(i = 0; i < fstab_file[fidx].numrecords; i++) { |
| if(fstab_equal(fstab_file[fidx].data[i], fstabentry) == BOOL_TRUE) { |
| return i; |
| } |
| } |
| |
| return -1; |
| } |
| |
| void * |
| remmap_fstab(int fidx, int num) |
| { |
| int i; |
| int nEntries; |
| char *mapaddr; |
| invt_fstab_t *fstab_entry; |
| |
| nEntries = fstab_file[fidx].counter->ic_curnum; |
| |
| munmap( fstab_file[fidx].mapaddr, |
| (nEntries * sizeof(invt_fstab_t)) + sizeof(invt_counter_t)); |
| |
| /* need to lseek on the file to grow it to the right size - no autogrow on linux */ |
| lseek(fstab_file[fidx].fd, (num * sizeof(invt_fstab_t)) - 1, SEEK_END); |
| write_n_bytes(fstab_file[fidx].fd, "", 1, fstab_file[fidx].name); |
| |
| mapaddr = mmap_n_bytes(fstab_file[fidx].fd, |
| (nEntries + 1) * (num * sizeof(invt_fstab_t)) |
| + sizeof(invt_counter_t), |
| BOOL_FALSE, |
| fstab_file[fidx].name); |
| |
| fstab_file[fidx].nEntries += num; |
| fstab_file[fidx].mapaddr = mapaddr; |
| fstab_file[fidx].counter = (invt_counter_t *)mapaddr; |
| |
| /* regenerate the data index for the file given the new mapping */ |
| fstab_entry = (invt_fstab_t *)(fstab_file[fidx].mapaddr + sizeof(invt_counter_t)); |
| for(i=0; i < nEntries; i++) { |
| if(i >= fstab_file[fidx].numrecords) { |
| add_fstab_data(fidx, &(fstab_entry[i])); |
| } |
| else { |
| fstab_file[fidx].data[i] = &(fstab_entry[i]); |
| } |
| } |
| |
| return &(fstab_entry[i]); |
| } |
| |
| int |
| open_fstab(char *fstabname) |
| { |
| int fd; |
| int nEntries; |
| char *mapaddr; |
| char *name; |
| invt_counter_t cnt; |
| |
| fd = open_and_lock( fstabname, FILE_WRITE, wait_for_locks ); |
| if (fd < 0) { |
| fprintf( stderr, "%s: abnormal termination\n", g_programName ); |
| exit(1); |
| } |
| |
| name = strdup(fstabname); |
| if(name == NULL) { |
| fprintf(stderr, "%s: internal memory error: strdup fstabname\n", g_programName); |
| exit(1); |
| } |
| |
| read_n_bytes(fd, &cnt, sizeof(invt_counter_t), fstabname); |
| |
| nEntries = cnt.ic_curnum; |
| |
| mapaddr = mmap_n_bytes(fd, |
| nEntries * sizeof(invt_fstab_t) + sizeof(invt_counter_t), |
| BOOL_FALSE, |
| fstabname); |
| |
| return add_fstab(name, fd, nEntries, mapaddr, (invt_counter_t *)mapaddr); |
| } |
| |
| int |
| close_fstab(int fidx) |
| { |
| int fstabentries; |
| |
| fstabentries = fstab_file[fidx].counter->ic_curnum; |
| |
| munmap( fstab_file[fidx].mapaddr, |
| (fstab_file[fidx].counter->ic_curnum * sizeof(invt_fstab_t)) + sizeof(invt_counter_t)); |
| |
| if ((fstabentries != 0) && (fstabentries < fstab_file[fidx].nEntries)) { |
| ftruncate(fstab_file[fidx].fd, |
| sizeof(invt_counter_t) + (sizeof(invt_fstab_t) * fstabentries)); |
| } |
| |
| close(fstab_file[fidx].fd); |
| |
| if (fstabentries == 0) { |
| unlink( fstab_file[fidx].name ); |
| } |
| |
| free(fstab_file[fidx].name); |
| free(fstab_file[fidx].data); |
| |
| return 0; |
| } |
| |
| int |
| close_all_fstab() |
| { |
| int i; |
| |
| for(i = 0; i < fstab_numfiles; i++) { |
| close_fstab(i); |
| } |
| |
| free(fstab_file); |
| fstab_file = NULL; |
| return 0; |
| } |