static const entry_t * get_pri_dirs(void) { int fd, state; size_t sz; ssize_t size; struct stat64 sb; char *buf, *ebuf; entry_t *vec; /* * if no /etc/ttysrch, use defaults */ if ((fd = open(TTYSRCH, 0)) < 0) return (def_srch_dirs); if (fstat64(fd, &sb) < 0) { (void) close(fd); return (def_srch_dirs); } sz = (size_t)sb.st_size; if (dir_vec != NULL && sz == dir_size && sb.st_mtim.tv_sec == dir_mtim.tv_sec && sb.st_mtim.tv_nsec == dir_mtim.tv_nsec) { /* * size & modification time match * no need to reread TTYSRCH * just return old pointer */ (void) close(fd); return (dir_vec); } buf = realloc(dir_buf, sz + 1); if (buf != NULL) { dir_buf = buf; size = read(fd, dir_buf, sz); } (void) close(fd); if (buf == NULL || size < 0) { if (dir_vec != NULL) { free(dir_vec); dir_vec = NULL; } return ((entry_t *)def_srch_dirs); } dir_size = sz; dir_mtim = sb.st_mtim; /* * ensure newline termination for buffer. Add an extra * entry to dir_vec for null terminator */ ebuf = &dir_buf[size]; *ebuf++ = '\n'; for (sz = 1, buf = dir_buf; buf < ebuf; ++buf) if (*buf == '\n') ++sz; sz *= sizeof (*dir_vec); vec = realloc(dir_vec, sz); if (vec == NULL) { if (dir_vec != NULL) { free(dir_vec); dir_vec = NULL; } return (def_srch_dirs); } dir_vec = vec; state = START_STATE; for (buf = dir_buf; buf < ebuf; ++buf) { switch (state) { case START_STATE: if (*buf == COMMENT_CHAR) { state = COMMENT_STATE; break; } if (!isspace(*buf)) /* skip leading white space */ state = DIRNAME_STATE; vec->name = buf; vec->flags = 0; break; case COMMENT_STATE: if (*buf == EOLN_CHAR) state = START_STATE; break; case DIRNAME_STATE: if (*buf == EOLN_CHAR) { state = CHECK_STATE; *buf = '\0'; } else if (isspace(*buf)) { /* skip trailing white space */ state = FLAG_STATE; *buf = '\0'; } break; case FLAG_STATE: switch (*buf) { case 'M': vec->flags |= MATCH_MM; break; case 'F': vec->flags |= MATCH_FS; break; case 'I': vec->flags |= MATCH_INO; break; case EOLN_CHAR: state = CHECK_STATE; break; } break; case CHECK_STATE: if (strncmp(vec->name, DEV, strlen(DEV)) != 0) { int tfd = open("/dev/console", O_WRONLY); if (tfd >= 0) { char buf[256]; /* LINTED variable format specifier */ (void) snprintf(buf, sizeof (buf), _libc_gettext( "ERROR: Entry '%s' in /etc/ttysrch ignored.\n"), vec->name); (void) write(tfd, buf, strlen(buf)); (void) close(tfd); } } else { char *slash; slash = vec->name + strlen(vec->name) - 1; while (*slash == '/') *slash-- = '\0'; if (vec->flags == 0) vec->flags = MATCH_ALL; vec++; } state = START_STATE; /* * This state does not consume a character, so * reposition the pointer. */ buf--; break; } } vec->name = NULL; return (dir_vec); }
int __part_load_locale(const char *name, int *using_locale, char *locale_buf, const char *category_filename, int locale_buf_size_max, int locale_buf_size_min, const char **dst_localebuf) { static char locale_buf_C[] = "C"; static int num_lines; int fd; char *lbuf; char *p; const char *plim; char filename[PATH_MAX]; #ifdef __USE_INTERNAL_STAT64 struct stat64 st; #else struct stat st; #endif size_t namesize; size_t bufsize; int save_using_locale; char *nptr; save_using_locale = *using_locale; *using_locale = 0; if (name == NULL) goto no_locale; if (!strcmp(name, "C") || !strcmp(name, "POSIX")) return 0; /* XXX: when adding cxx support the function failed to compile, so * the missing functions below were commented out. * adding this message here to abort and warn the user */ printf("__part_load_locale not implemented!\n"); abort(); /* * If the locale name is the same as our cache, use the cache. */ lbuf = locale_buf; if (lbuf != NULL && strcmp(name, lbuf) == 0) { set_from_buf(lbuf, num_lines, dst_localebuf); *using_locale = 1; return 0; } /* * Slurp the locale file into the cache. */ namesize = strlen(name) + 1; if (!_PathLocale) goto no_locale; /* Range checking not needed, 'name' size is limited */ strcpy(filename, _PathLocale); strcat(filename, "/"); strcat(filename, name); strcat(filename, "/"); strcat(filename, category_filename); //fd = open(filename, O_RDONLY); if (fd < 0) goto no_locale; #ifdef __USE_INTERNAL_STAT64 if (fstat64(fd, &st) != 0) #else //if (fstat(fd, &st) != 0) #endif // goto bad_locale; if (st.st_size <= 0) goto bad_locale; bufsize = namesize + st.st_size + 1; locale_buf = NULL; if (lbuf == NULL || lbuf == locale_buf_C) { lbuf = malloc(bufsize); } else { nptr = realloc(lbuf, bufsize); if (!nptr && lbuf) free (lbuf); lbuf = nptr; } if (lbuf == NULL) goto bad_locale; (void) strcpy(lbuf, name); p = lbuf + namesize; plim = p + st.st_size; //if (read(fd, p, (size_t) st.st_size) != st.st_size) // goto bad_lbuf; //if (close(fd) != 0) // goto bad_lbuf; /* * Parse the locale file into localebuf. */ p[st.st_size] = '\0'; if (plim[-1] != '\n') goto bad_lbuf; num_lines = split_lines(p, plim); if (num_lines >= locale_buf_size_max) num_lines = locale_buf_size_max; else if (num_lines >= locale_buf_size_min) num_lines = locale_buf_size_min; else goto reset_locale; set_from_buf(lbuf, num_lines, dst_localebuf); /* * Record the successful parse in the cache. */ locale_buf = lbuf; *using_locale = 1; return 0; reset_locale: locale_buf = locale_buf_C; save_using_locale = 0; bad_lbuf: free(lbuf); bad_locale: //(void)close(fd); no_locale: *using_locale = save_using_locale; return -1; }
/* * Name: compute_checksum * Description: generate checksum for specified file * Arguments: r_cksumerr (int *) [RO, *RW] * - pointer to integer that is set on return to: * == 0 - no error occurred * != 0 - error occurred * a_path (char *) [RO, *RO] * - pointer to string representing path to file to * generate checksum of * Returns: unsigned long - results: * - If *r_cksumerr == 0, checksum of specified file * - If *r_cksumerr != 0, undefined */ unsigned long compute_checksum(int *r_cksumerr, char *a_path) { CHECKSUM_T suma; /* to split four-bytes into 2 two-byte values */ CHECKSUM_T tempa; int fd; uint32_t lg; /* running checksum value */ uint32_t buf[CHUNK/4]; /* to read CHUNK bytes */ uint32_t lsavhi; /* high order two-bytes of four-byte checksum */ uint32_t lsavlo; /* low order two-bytes of four-byte checksum */ int leap = sizeof (uint32_t); int notyet = 0; int nread; struct stat64 sbuf; /* reset error flag */ *r_cksumerr = 0; /* open file and obtain -> where file is mapped/read */ if ((fd = open(a_path, O_RDONLY)) < 0) { *r_cksumerr = 1; reperr(pkg_gt(ERR_NO_CKSUM)); perror(ERR_NO_CKSUM); return (0); } if (fstat64(fd, &sbuf) != 0) { *r_cksumerr = 1; reperr(pkg_gt(ERR_NO_CKSUM)); perror(ERR_NO_CKSUM); return (0); } /* initialize checksum value */ lg = 0; /* * Read CHUNK bytes off the file at a time; Read size of long bytes * from memory at a time and process them. * If last read, then read remnant bytes and process individually. */ errno = 0; while ((nread = read(fd, (void*)buf, (sbuf.st_size < CHUNK) ? sbuf.st_size : CHUNK)) > 0) { uchar_t *s; uint32_t *p = buf; notyet = nread % leap; nread -= notyet; for (; nread > 0; nread -= leap) { lg += ((((*p)>>24)&0xFF) & WDMSK); lg += ((((*p)>>16)&0xFF) & WDMSK); lg += ((((*p)>>8)&0xFF) & WDMSK); lg += (((*p)&0xFF) & WDMSK); p++; } s = (uchar_t *)p; /* leftover bytes less than four in number */ while (notyet--) lg += (((uint32_t)(*s++)) & WDMSK); } /* wind up */ (void) close(fd); /* compute checksum components */ suma.lg = lg; tempa.lg = (suma.hl.lo & WDMSK) + (suma.hl.hi & WDMSK); lsavhi = (uint32_t)tempa.hl.hi; lsavlo = (uint32_t)tempa.hl.lo; /* return final checksum value */ return (lsavhi+lsavlo); }
int main(int argc, char *argv[]) { int fd = 0, disk = 0; int ret; int offset; unsigned long c = 0; int block_size, block_count, block_num; off64_t block_off, seek_ret; struct stat64 statinfo; struct timeval start_time, end_time; char *membuf = NULL; unsigned char *buf; //unsigned char buf[BLK_SIZE] __attribute__ ((__aligned__ (BLK_SIZE))); //buf = (unsigned char *)memalign(BLK_SIZE, BLK_SIZE); //if (!buf) { // fprintf(stderr, "failed to allocate memory\n"); // goto err; //} /* Allocate memory on page boundary */ ret = posix_memalign((void **)&buf, BLK_SIZE, BLK_SIZE); if (ret != 0) { fprintf(stderr, "Failed to allocate memory\n"); goto err; } if (argc != 3) { fprintf(stderr, "Invalid number of arguments\n" "Format : $./directio <partition> <file>\n" "Example : $./directio /dev/sda1 ~/test.dump\n"); goto err; } /* open partition */ disk = open(argv[1], O_RDONLY | O_DIRECT | O_LARGEFILE); if (disk <= 0) { fprintf(stderr, "Cannot open partition %s\n", argv[1]); goto err; } /* open file */ fd = open(argv[2], O_RDONLY | O_DIRECT | O_LARGEFILE); if (fd <= 0) { fprintf(stderr, "Cannot open file %s\n", argv[2]); goto err; } /* allocate buffer */ membuf = malloc(BUF_SIZE); if (!membuf) { fprintf(stderr, "Failed to allocate memory\n"); goto err; } /* get block size */ if (ioctl(fd, FIGETBSZ, &block_size) < 0) { fprintf(stderr, "Failed to get block size\n"); goto err; } /* get number of blocks of file */ if (fstat64(fd, &statinfo) < 0) { fprintf(stderr, "Stat failed\n"); goto err; } /* calculate number of blocks for the file */ block_count = (statinfo.st_size + block_size - 1) / block_size; fprintf(stdout, "File : %s block_count = %d, block_size = %d\n", argv[2], block_count, block_size); offset = 0; gettimeofday(&start_time, 0); for (c = 0; c < block_count; c++) { /* get next block number allocated to file */ block_num = c; if (ioctl(fd, FIBMAP, &block_num)) { fprintf(stderr, "IOCTL failed\n"); } /* seek to the block directly on disk */ block_off = (off64_t)block_num * (off64_t)block_size; seek_ret = lseek64(disk, block_off, SEEK_SET); if (seek_ret < 0) { fprintf(stderr, "Seek error at %lu - %lu\n", (unsigned long)block_off, (unsigned long)seek_ret); goto err; } /* read the block directly from disk */ if (read(disk, buf, BLK_SIZE) != BLK_SIZE) { fprintf(stderr, "Read error at %lu\n", (long)block_off); goto err; } /* copy data to memory buffer of 10 MB */ memcpy(membuf + offset, buf, BLK_SIZE); offset += 4096; if (offset >= BUF_SIZE) { printf("block_count = %lu / %d\n", c, block_count); offset = 0; /* reset buffer when end reached */ } } gettimeofday(&end_time, 0); fprintf(stdout, "Time taken : %lu\n", end_time.tv_sec - start_time.tv_sec); return 0; err: if (membuf) free(membuf); if (fd > 0) close(fd); if (disk > 0) close(disk); if (buf) free(buf); return -1; }
char * gettxt(const char *msg_id, const char *dflt_str) { struct db_cache *dbc; struct db_list *dbl; char msgfile[DB_NAME_LEN]; /* name of static shared library */ int msgnum; /* message number */ char pathname[PATH_MAX]; /* full pathname to message file */ int fd; struct stat64 sb; void *addr; char *tokp; size_t name_len; char *curloc; if ((msg_id == NULL) || (*msg_id == '\0')) { return (handle_return(dflt_str)); } /* parse msg_id */ if (((tokp = strchr(msg_id, ':')) == NULL) || *(tokp+1) == '\0') return (handle_return(dflt_str)); if ((name_len = (tokp - msg_id)) >= DB_NAME_LEN) return (handle_return(dflt_str)); if (name_len > 0) { (void) strncpy(msgfile, msg_id, name_len); msgfile[name_len] = '\0'; } else { lrw_rdlock(&_rw_cur_cat); if (cur_cat == NULL || *cur_cat == '\0') { lrw_unlock(&_rw_cur_cat); return (handle_return(dflt_str)); } /* * We know the following strcpy is safe. */ (void) strcpy(msgfile, cur_cat); lrw_unlock(&_rw_cur_cat); } while (*++tokp) { if (!isdigit((unsigned char)*tokp)) return (handle_return(dflt_str)); } msgnum = atoi(msg_id + name_len + 1); curloc = setlocale(LC_MESSAGES, NULL); lmutex_lock(&gettxt_lock); try_C: dbc = db_cache; while (dbc) { if (strcmp(curloc, dbc->loc) == 0) { dbl = dbc->info; while (dbl) { if (strcmp(msgfile, dbl->db_name) == 0) { /* msgfile found */ lmutex_unlock(&gettxt_lock); goto msgfile_found; } dbl = dbl->next; } /* not found */ break; } dbc = dbc->next; } if (dbc == NULL) { /* new locale */ if ((dbc = lmalloc(sizeof (struct db_cache))) == NULL) { lmutex_unlock(&gettxt_lock); return (handle_return(dflt_str)); } if ((dbc->loc = lmalloc(strlen(curloc) + 1)) == NULL) { lfree(dbc, sizeof (struct db_cache)); lmutex_unlock(&gettxt_lock); return (handle_return(dflt_str)); } dbc->info = NULL; (void) strcpy(dbc->loc, curloc); /* connect dbc to the dbc list */ dbc->next = db_cache; db_cache = dbc; } if ((dbl = lmalloc(sizeof (struct db_list))) == NULL) { lmutex_unlock(&gettxt_lock); return (handle_return(dflt_str)); } if (snprintf(pathname, sizeof (pathname), _DFLT_LOC_PATH "%s" MESSAGES "%s", dbc->loc, msgfile) >= sizeof (pathname)) { lfree(dbl, sizeof (struct db_list)); lmutex_unlock(&gettxt_lock); return (handle_return(dflt_str)); } if ((fd = open(pathname, O_RDONLY)) == -1 || fstat64(fd, &sb) == -1 || (addr = mmap(NULL, (size_t)sb.st_size, PROT_READ, MAP_SHARED, fd, 0L)) == MAP_FAILED) { if (fd != -1) (void) close(fd); lfree(dbl, sizeof (struct db_list)); if (strcmp(dbc->loc, "C") == 0) { lmutex_unlock(&gettxt_lock); return (handle_return(dflt_str)); } /* Change locale to C */ curloc = (char *)loc_C; goto try_C; } (void) close(fd); /* save file name, memory address, fd and size */ (void) strcpy(dbl->db_name, msgfile); dbl->addr = (uintptr_t)addr; /* connect dbl to the dbc->info list */ dbl->next = dbc->info; dbc->info = dbl; lmutex_unlock(&gettxt_lock); msgfile_found: /* check if msgnum out of domain */ if (msgnum <= 0 || msgnum > *(int *)dbl->addr) return (handle_return(dflt_str)); /* return pointer to message */ return ((char *)(dbl->addr + *(int *)(dbl->addr + msgnum * sizeof (int)))); }
static int undo_one (void **p, void *info) { struct prelink_entry *ent = * (struct prelink_entry **) p; DSO *dso; struct stat64 st; struct prelink_link *hardlink; char *move = NULL; size_t movelen = 0; if (ent->done != 2) return 1; if (ent->type != ET_DYN && (ent->type != ET_EXEC || libs_only)) return 1; dso = open_dso (ent->canon_filename); if (dso == NULL) goto error_out; if (fstat64 (dso->fd, &st) < 0) { error (0, errno, "%s changed during prelinking", ent->filename); goto error_out; } if (st.st_dev != ent->dev || st.st_ino != ent->ino) { error (0, 0, "%s changed during prelinking", ent->filename); goto error_out; } if (verbose) { if (dry_run) printf ("Would undo %s\n", ent->canon_filename); else printf ("Undoing %s\n", ent->canon_filename); } if (prelink_undo (dso)) goto error_out; if (dry_run) close_dso (dso); else { if (update_dso (dso, NULL)) { dso = NULL; goto error_out; } } dso = NULL; /* Redo hardlinks. */ for (hardlink = ent->hardlink; hardlink; hardlink = hardlink->next) { size_t len; if (lstat64 (hardlink->canon_filename, &st) < 0) { error (0, 0, "Could not stat %s (former hardlink to %s)", hardlink->canon_filename, ent->canon_filename); continue; } if (st.st_dev != ent->dev || st.st_ino != ent->ino) { error (0, 0, "%s is no longer hardlink to %s", hardlink->canon_filename, ent->canon_filename); continue; } if (verbose) { if (dry_run) printf ("Would link %s to %s\n", hardlink->canon_filename, ent->canon_filename); else printf ("Linking %s to %s\n", hardlink->canon_filename, ent->canon_filename); } len = strlen (hardlink->canon_filename); if (len + sizeof (".#prelink#") > movelen) { movelen = len + sizeof (".#prelink#"); move = realloc (move, movelen); if (move == NULL) { error (0, ENOMEM, "Could not hardlink %s to %s", hardlink->canon_filename, ent->canon_filename); movelen = 0; continue; } } memcpy (mempcpy (move, hardlink->canon_filename, len), ".#prelink#", sizeof (".#prelink#")); if (rename (hardlink->canon_filename, move) < 0) { error (0, errno, "Could not hardlink %s to %s", hardlink->canon_filename, ent->canon_filename); continue; } if (link (ent->canon_filename, hardlink->canon_filename) < 0) { error (0, errno, "Could not hardlink %s to %s", hardlink->canon_filename, ent->canon_filename); if (rename (move, hardlink->canon_filename) < 0) { error (0, errno, "Could not rename %s back to %s", move, hardlink->canon_filename); } continue; } if (unlink (move) < 0) { error (0, errno, "Could not unlink %s", move); continue; } } free (move); return 1; error_out: if (dso) close_dso (dso); (*(int *)info)++; return 1; }
int vn_fromfd(int fd, char *path, int flags, struct vnode **vpp, boolean_t fromfd) { int save_errno; vnode_t *vp; *vpp = vp = kmem_cache_alloc(vnode_cache, KM_SLEEP); memset(vp, 0, sizeof(vnode_t)); if (fstat64(fd, &vp->v_stat) == -1) { save_errno = errno; close(fd); return (save_errno); } (void) fcntl(fd, F_SETFD, FD_CLOEXEC); vp->v_fd = fd; if(S_ISBLK(vp->v_stat.st_mode)) { /* LINUX */ if(ioctl(fd, BLKGETSIZE64, &vp->v_size) != 0) { save_errno = errno; close(fd); return (save_errno); } } else vp->v_size = vp->v_stat.st_size; vp->v_path = strdup(path); vp->v_type = VNON; if(fromfd) vn_setops(vp, fd_fvnodeops); else vn_setops(vp, root_fvnodeops); if(S_ISREG(vp->v_stat.st_mode)) { vp->v_type = VREG; if (flags & FREAD) atomic_add_32(&((*vpp)->v_rdcnt), 1); if (flags & FWRITE) atomic_add_32(&((*vpp)->v_wrcnt), 1); } else if(S_ISDIR(vp->v_stat.st_mode)) vp->v_type = VDIR; else if(S_ISCHR(vp->v_stat.st_mode)) vp->v_type = VCHR; else if(S_ISBLK(vp->v_stat.st_mode)) vp->v_type = VBLK; else if(S_ISFIFO(vp->v_stat.st_mode)) vp->v_type = VFIFO; else if(S_ISLNK(vp->v_stat.st_mode)) vp->v_type = VLNK; else if(S_ISSOCK(vp->v_stat.st_mode)) vp->v_type = VSOCK; VERIFY(vp->v_type != VNON); zmutex_init(&vp->v_lock); rwst_init(&vp->v_vfsmhlock.ve_lock, NULL, RW_DEFAULT, NULL); vp->v_count = 1; vp->v_vfsp = rootvfs; /*fprintf(stderr, "VNode %p created at vn_open (%s)\n", *vpp, path);*/ return (0); }
static int usd_FileIoctl(usd_handle_t usd, int req, void *arg) { int fd = (intptr_t)(usd->handle); #ifdef O_LARGEFILE struct stat64 info; #else /* O_LARGEFILE */ struct stat info; #endif /* O_LARGEFILE */ #ifdef AFS_AIX_ENV struct statfs fsinfo; /* AIX stat structure doesn't have st_blksize */ #endif /* AFS_AIX_ENV */ afs_int64 size; int code = 0; switch (req) { case USD_IOCTL_GETBLKSIZE: #ifdef AFS_AIX_ENV code = fstatfs(fd, &fsinfo); if (code) { *((long *)arg) = (long)4096; return 0; } break; #endif /* AFS_AIX_ENV */ case USD_IOCTL_GETTYPE: case USD_IOCTL_GETDEV: case USD_IOCTL_GETSIZE: #ifdef O_LARGEFILE code = fstat64(fd, &info); #else /* O_LARGEFILE */ code = fstat(fd, &info); #endif /* O_LARGEFILE */ if (code) return errno; break; } switch (req) { case USD_IOCTL_GETTYPE: *(int *)arg = info.st_mode & S_IFMT; break; case USD_IOCTL_GETDEV: if (!(S_ISCHR(info.st_mode) || S_ISBLK(info.st_mode))) return ENODEV; /* not a device */ *(dev_t *) arg = info.st_rdev; break; case USD_IOCTL_GETSIZE: if (S_ISCHR(info.st_mode) || S_ISBLK(info.st_mode)) return ENOTTY; /* shouldn't be a device */ *(afs_int64 *)arg = info.st_size; break; case USD_IOCTL_GETFULLNAME: *(char **)arg = usd->fullPathName; break; case USD_IOCTL_SETSIZE: /* We could just use ftruncate in all cases. (This even works on AIX; * I tried it). -blake 931118 */ /* However, I'm pretty sure this doesn't work on Ultrix so I am * unsure about OSF/1 and HP/UX. 931118 */ size = *(afs_int64 *) arg; if (!osi_hFitsInOff(size)) return EFBIG; #ifdef O_LARGEFILE code = ftruncate64(fd, size); #else /* O_LARGEFILE */ code = ftruncate(fd, size); #endif /* O_LARGEFILE */ if (code == -1) code = errno; return code; case USD_IOCTL_TAPEOPERATION: { #ifdef AFS_DARWIN100_ENV code = EOPNOTSUPP; #else usd_tapeop_t *tapeOpp = (usd_tapeop_t *) arg; #if defined(AFS_AIX_ENV) struct stop os_tapeop; if (tapeOpp->tp_op == USDTAPE_WEOF) { os_tapeop.st_op = STWEOF; } else if (tapeOpp->tp_op == USDTAPE_REW) { os_tapeop.st_op = STREW; } else if (tapeOpp->tp_op == USDTAPE_FSF) { os_tapeop.st_op = STFSF; } else if (tapeOpp->tp_op == USDTAPE_BSF) { os_tapeop.st_op = STRSF; } else if (tapeOpp->tp_op == USDTAPE_PREPARE) { return 0; } else if (tapeOpp->tp_op == USDTAPE_SHUTDOWN) { return 0; } else { /* unsupported tape operation */ return EINVAL; } os_tapeop.st_count = tapeOpp->tp_count; code = ioctl(fd, STIOCTOP, &os_tapeop); #else struct mtop os_tapeop; if (tapeOpp->tp_op == USDTAPE_WEOF) { os_tapeop.mt_op = MTWEOF; } else if (tapeOpp->tp_op == USDTAPE_REW) { os_tapeop.mt_op = MTREW; } else if (tapeOpp->tp_op == USDTAPE_FSF) { os_tapeop.mt_op = MTFSF; } else if (tapeOpp->tp_op == USDTAPE_BSF) { os_tapeop.mt_op = MTBSF; } else if (tapeOpp->tp_op == USDTAPE_PREPARE) { return 0; } else if (tapeOpp->tp_op == USDTAPE_SHUTDOWN) { return 0; } else { /* unsupported tape operation */ return EINVAL; } os_tapeop.mt_count = tapeOpp->tp_count; code = ioctl(fd, MTIOCTOP, &os_tapeop); #endif /* AFS_AIX_ENV */ #endif if (code == -1) { code = errno; } else { code = 0; } return code; } case USD_IOCTL_GETBLKSIZE: if (S_ISCHR(info.st_mode) || S_ISBLK(info.st_mode)) { *((long *)arg) = (long)4096; return 0; } #ifdef AFS_AIX_ENV *((long *)arg) = (long)fsinfo.f_bsize; #else /* AFS_AIX_ENV */ *((long *)arg) = (long)info.st_blksize; #endif /* AFS_AIX_ENV */ break; default: return EINVAL; } return code; }
/* * Given a cache file, return the contents as a list of importable pools. * poolname or guid (but not both) are provided by the caller when trying * to import a specific pool. */ nvlist_t * zpool_find_import_cached(libzfs_handle_t *hdl, const char *cachefile, char *poolname, uint64_t guid) { char *buf; int fd; struct stat64 statbuf; nvlist_t *raw, *src, *dst; nvlist_t *pools; nvpair_t *elem; char *name; uint64_t this_guid; boolean_t active; verify(poolname == NULL || guid == 0); if ((fd = open(cachefile, O_RDONLY)) < 0) { zfs_error_aux(hdl, "%s", strerror(errno)); (void) zfs_error(hdl, EZFS_BADCACHE, dgettext(TEXT_DOMAIN, "failed to open cache file")); return (NULL); } if (fstat64(fd, &statbuf) != 0) { zfs_error_aux(hdl, "%s", strerror(errno)); (void) close(fd); (void) zfs_error(hdl, EZFS_BADCACHE, dgettext(TEXT_DOMAIN, "failed to get size of cache file")); return (NULL); } if ((buf = zfs_alloc(hdl, statbuf.st_size)) == NULL) { (void) close(fd); return (NULL); } if (read(fd, buf, statbuf.st_size) != statbuf.st_size) { (void) close(fd); free(buf); (void) zfs_error(hdl, EZFS_BADCACHE, dgettext(TEXT_DOMAIN, "failed to read cache file contents")); return (NULL); } (void) close(fd); if (nvlist_unpack(buf, statbuf.st_size, &raw, 0) != 0) { free(buf); (void) zfs_error(hdl, EZFS_BADCACHE, dgettext(TEXT_DOMAIN, "invalid or corrupt cache file contents")); return (NULL); } free(buf); /* * Go through and get the current state of the pools and refresh their * state. */ if (nvlist_alloc(&pools, 0, 0) != 0) { (void) no_memory(hdl); nvlist_free(raw); return (NULL); } elem = NULL; while ((elem = nvlist_next_nvpair(raw, elem)) != NULL) { verify(nvpair_value_nvlist(elem, &src) == 0); verify(nvlist_lookup_string(src, ZPOOL_CONFIG_POOL_NAME, &name) == 0); if (poolname != NULL && strcmp(poolname, name) != 0) continue; verify(nvlist_lookup_uint64(src, ZPOOL_CONFIG_POOL_GUID, &this_guid) == 0); if (guid != 0) { verify(nvlist_lookup_uint64(src, ZPOOL_CONFIG_POOL_GUID, &this_guid) == 0); if (guid != this_guid) continue; } if (pool_active(hdl, name, this_guid, &active) != 0) { nvlist_free(raw); nvlist_free(pools); return (NULL); } if (active) continue; if ((dst = refresh_config(hdl, src)) == NULL) { nvlist_free(raw); nvlist_free(pools); return (NULL); } if (nvlist_add_nvlist(pools, nvpair_name(elem), dst) != 0) { (void) no_memory(hdl); nvlist_free(dst); nvlist_free(raw); nvlist_free(pools); return (NULL); } nvlist_free(dst); } nvlist_free(raw); return (pools); }
int main (int argc, char ** argv) { errcode_t retval; ext2_filsys fs; int c; int flags = 0; int flush = 0; int force = 0; int io_flags = 0; int force_min_size = 0; int print_min_size = 0; int fd, ret; blk64_t new_size = 0; blk64_t max_size = 0; blk64_t min_size = 0; io_manager io_ptr; char *new_size_str = 0; int use_stride = -1; #ifdef HAVE_FSTAT64 struct stat64 st_buf; #else struct stat st_buf; #endif __s64 new_file_size; unsigned int sys_page_size = 4096; long sysval; int len, mount_flags; char *mtpt; #ifdef ENABLE_NLS setlocale(LC_MESSAGES, ""); setlocale(LC_CTYPE, ""); bindtextdomain(NLS_CAT_NAME, LOCALEDIR); textdomain(NLS_CAT_NAME); set_com_err_gettext(gettext); #endif add_error_table(&et_ext2_error_table); fprintf (stderr, "resize2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE); if (argc && *argv) program_name = *argv; while ((c = getopt (argc, argv, "d:fFhMPpS:")) != EOF) { switch (c) { case 'h': usage(program_name); break; case 'f': force = 1; break; case 'F': flush = 1; break; case 'M': force_min_size = 1; break; case 'P': print_min_size = 1; break; case 'd': flags |= atoi(optarg); break; case 'p': flags |= RESIZE_PERCENT_COMPLETE; break; case 'S': use_stride = atoi(optarg); break; default: usage(program_name); } } if (optind == argc) usage(program_name); device_name = argv[optind++]; if (optind < argc) new_size_str = argv[optind++]; if (optind < argc) usage(program_name); io_options = strchr(device_name, '?'); if (io_options) *io_options++ = 0; /* * Figure out whether or not the device is mounted, and if it is * where it is mounted. */ len=80; while (1) { mtpt = malloc(len); if (!mtpt) return ENOMEM; mtpt[len-1] = 0; retval = ext2fs_check_mount_point(device_name, &mount_flags, mtpt, len); if (retval) { com_err("ext2fs_check_mount_point", retval, _("while determining whether %s is mounted."), device_name); exit(1); } if (!(mount_flags & EXT2_MF_MOUNTED) || (mtpt[len-1] == 0)) break; free(mtpt); len = 2 * len; } fd = ext2fs_open_file(device_name, O_RDWR, 0); if (fd < 0) { com_err("open", errno, _("while opening %s"), device_name); exit(1); } #ifdef HAVE_FSTAT64 ret = fstat64(fd, &st_buf); #else ret = fstat(fd, &st_buf); #endif if (ret < 0) { com_err("open", errno, _("while getting stat information for %s"), device_name); exit(1); } if (flush) { retval = ext2fs_sync_device(fd, 1); if (retval) { com_err(argv[0], retval, _("while trying to flush %s"), device_name); exit(1); } } if (!S_ISREG(st_buf.st_mode )) { close(fd); fd = -1; } #ifdef CONFIG_TESTIO_DEBUG if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) { io_ptr = test_io_manager; test_io_backing_manager = unix_io_manager; } else #endif io_ptr = unix_io_manager; if (!(mount_flags & EXT2_MF_MOUNTED)) io_flags = EXT2_FLAG_RW | EXT2_FLAG_EXCLUSIVE; retval = ext2fs_open2(device_name, io_options, io_flags, 0, 0, io_ptr, &fs); if (retval) { com_err (program_name, retval, _("while trying to open %s"), device_name); printf (_("Couldn't find valid filesystem superblock.\n")); exit (1); } /* * Check for compatibility with the feature sets. We need to * be more stringent than ext2fs_open(). */ if (fs->super->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) { com_err(program_name, EXT2_ET_UNSUPP_FEATURE, "(%s)", device_name); exit(1); } /* * XXXX The combination of flex_bg and !resize_inode causes * major problems for resize2fs, since when the group descriptors * grow in size this can potentially require multiple inode * tables to be moved aside to make room, and resize2fs chokes * rather badly in this scenario. It's a rare combination, * except when a filesystem is expanded more than a certain * size, so for now, we'll just prohibit that combination. * This is something we should fix eventually, though. */ if ((fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_FLEX_BG) && !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_RESIZE_INODE)) { com_err(program_name, 0, _("%s: The combination of flex_bg " "and\n\t!resize_inode features " "is not supported by resize2fs.\n"), device_name); exit(1); } min_size = calculate_minimum_resize_size(fs); if (print_min_size) { if (!force && ((fs->super->s_state & EXT2_ERROR_FS) || ((fs->super->s_state & EXT2_VALID_FS) == 0))) { fprintf(stderr, _("Please run 'e2fsck -f %s' first.\n\n"), device_name); exit(1); } printf(_("Estimated minimum size of the filesystem: %llu\n"), min_size); exit(0); } /* Determine the system page size if possible */ #ifdef HAVE_SYSCONF #if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE)) #define _SC_PAGESIZE _SC_PAGE_SIZE #endif #ifdef _SC_PAGESIZE sysval = sysconf(_SC_PAGESIZE); if (sysval > 0) sys_page_size = sysval; #endif /* _SC_PAGESIZE */ #endif /* HAVE_SYSCONF */ /* * Get the size of the containing partition, and use this for * defaults and for making sure the new filesystem doesn't * exceed the partition size. */ retval = ext2fs_get_device_size2(device_name, fs->blocksize, &max_size); if (retval) { com_err(program_name, retval, _("while trying to determine filesystem size")); exit(1); } if (force_min_size) new_size = min_size; else if (new_size_str) { new_size = parse_num_blocks2(new_size_str, fs->super->s_log_block_size); if (new_size == 0) { com_err(program_name, 0, _("Invalid new size: %s\n"), new_size_str); exit(1); } } else { /* Take down devices exactly 16T to 2^32-1 blocks */ if (max_size == (1ULL << 32)) max_size--; else if (max_size > (1ULL << 32)) { com_err(program_name, 0, _("New size too large to be " "expressed in 32 bits\n")); exit(1); } new_size = max_size; /* Round down to an even multiple of a pagesize */ if (sys_page_size > fs->blocksize) new_size &= ~((sys_page_size / fs->blocksize)-1); } if (!force && new_size < min_size) { com_err(program_name, 0, _("New size smaller than minimum (%llu)\n"), min_size); exit(1); } if (use_stride >= 0) { if (use_stride >= (int) fs->super->s_blocks_per_group) { com_err(program_name, 0, _("Invalid stride length")); exit(1); } fs->stride = fs->super->s_raid_stride = use_stride; ext2fs_mark_super_dirty(fs); } else determine_fs_stride(fs); /* * If we are resizing a plain file, and it's not big enough, * automatically extend it in a sparse fashion by writing the * last requested block. */ new_file_size = ((__u64) new_size) * fs->blocksize; if ((__u64) new_file_size > (((__u64) 1) << (sizeof(st_buf.st_size)*8 - 1)) - 1) fd = -1; if ((new_file_size > st_buf.st_size) && (fd > 0)) { if ((ext2fs_llseek(fd, new_file_size-1, SEEK_SET) >= 0) && (write(fd, "0", 1) == 1)) max_size = new_size; } if (!force && (new_size > max_size)) { fprintf(stderr, _("The containing partition (or device)" " is only %llu (%dk) blocks.\nYou requested a new size" " of %llu blocks.\n\n"), max_size, fs->blocksize / 1024, new_size); exit(1); } if (new_size == ext2fs_blocks_count(fs->super)) { fprintf(stderr, _("The filesystem is already %llu blocks " "long. Nothing to do!\n\n"), new_size); exit(0); } if (mount_flags & EXT2_MF_MOUNTED) { retval = online_resize_fs(fs, mtpt, &new_size, flags); } else { if (!force && ((fs->super->s_lastcheck < fs->super->s_mtime) || (fs->super->s_state & EXT2_ERROR_FS) || ((fs->super->s_state & EXT2_VALID_FS) == 0))) { fprintf(stderr, _("Please run 'e2fsck -f %s' first.\n\n"), device_name); exit(1); } printf(_("Resizing the filesystem on " "%s to %llu (%dk) blocks.\n"), device_name, new_size, fs->blocksize / 1024); retval = resize_fs(fs, &new_size, flags, ((flags & RESIZE_PERCENT_COMPLETE) ? resize_progress_func : 0)); } free(mtpt); if (retval) { com_err(program_name, retval, _("while trying to resize %s"), device_name); fprintf(stderr, _("Please run 'e2fsck -fy %s' to fix the filesystem\n" "after the aborted resize operation.\n"), device_name); ext2fs_close(fs); exit(1); } printf(_("The filesystem on %s is now %llu blocks long.\n\n"), device_name, new_size); if ((st_buf.st_size > new_file_size) && (fd > 0)) { #ifdef HAVE_FTRUNCATE64 retval = ftruncate64(fd, new_file_size); #else retval = 0; /* Only truncate if new_file_size doesn't overflow off_t */ if (((off_t) new_file_size) == new_file_size) retval = ftruncate(fd, (off_t) new_file_size); #endif if (retval) com_err(program_name, retval, _("while trying to truncate %s"), device_name); } if (fd > 0) close(fd); remove_error_table(&et_ext2_error_table); return (0); }
static unsigned int call_syscall(struct syscall_desc *scall, char *argv[]) { struct stat64 sb; long long flags; unsigned int i; char *endp; int name, rval; union { char *str; long long num; } args[MAX_ARGS]; #ifdef HAS_FREEBSD_ACL int entry_id = ACL_FIRST_ENTRY; acl_t acl, newacl; acl_entry_t entry, newentry; #endif /* * Verify correctness of the arguments. */ for (i = 0; i < sizeof(args)/sizeof(args[0]); i++) { if (scall->sd_args[i] == TYPE_NONE) { if (argv[i] == NULL || strcmp(argv[i], ":") == 0) break; fprintf(stderr, "too many arguments [%s]\n", argv[i]); exit(1); } else { if (argv[i] == NULL || strcmp(argv[i], ":") == 0) { if (scall->sd_args[i] & TYPE_OPTIONAL) break; fprintf(stderr, "too few arguments\n"); exit(1); } if ((scall->sd_args[i] & TYPE_MASK) == TYPE_STRING) { if (strcmp(argv[i], "NULL") == 0) args[i].str = NULL; else if (strcmp(argv[i], "DEADCODE") == 0) args[i].str = (void *)0xdeadc0de; else args[i].str = argv[i]; } else if ((scall->sd_args[i] & TYPE_MASK) == TYPE_NUMBER) { args[i].num = strtoll(argv[i], &endp, 0); if (*endp != '\0' && !isspace((unsigned char)*endp)) { fprintf(stderr, "invalid argument %u, number expected [%s]\n", i, endp); exit(1); } } else if ((scall->sd_args[i] & TYPE_MASK) == TYPE_DESCRIPTOR) { if (strcmp(argv[i], "AT_FDCWD") == 0) { args[i].num = AT_FDCWD; } else if (strcmp(argv[i], "BADFD") == 0) { /* In case AT_FDCWD is -1 on some systems... */ if (AT_FDCWD == -1) args[i].num = -2; else args[i].num = -1; } else { int pos; pos = strtoll(argv[i], &endp, 0); if (*endp != '\0' && !isspace((unsigned char)*endp)) { fprintf(stderr, "invalid argument %u, number expected [%s]\n", i, endp); exit(1); } args[i].num = descriptor_get(pos); } } } } /* * Call the given syscall. */ #define NUM(n) (args[(n)].num) #define STR(n) (args[(n)].str) switch (scall->sd_action) { case ACTION_OPEN: flags = str2flags(open_flags, STR(1)); if (flags & O_CREAT) { if (i == 2) { fprintf(stderr, "too few arguments\n"); exit(1); } rval = open(STR(0), (int)flags, (mode_t)NUM(2)); } else { if (i == 3) { fprintf(stderr, "too many arguments\n"); exit(1); } rval = open(STR(0), (int)flags); } if (rval >= 0) descriptor_add(rval); break; case ACTION_OPENAT: flags = str2flags(open_flags, STR(2)); if (flags & O_CREAT) { if (i == 3) { fprintf(stderr, "too few arguments\n"); exit(1); } rval = openat(NUM(0), STR(1), (int)flags, (mode_t)NUM(3)); } else { if (i == 4) { fprintf(stderr, "too many arguments\n"); exit(1); } rval = openat(NUM(0), STR(1), (int)flags); } if (rval >= 0) descriptor_add(rval); break; case ACTION_CREATE: rval = open(STR(0), O_CREAT | O_EXCL, (mode_t)NUM(1)); if (rval >= 0) close(rval); break; case ACTION_UNLINK: rval = unlink(STR(0)); break; case ACTION_UNLINKAT: rval = unlinkat(NUM(0), STR(1), (int)str2flags(unlinkat_flags, STR(2))); break; case ACTION_MKDIR: rval = mkdir(STR(0), (mode_t)NUM(1)); break; case ACTION_MKDIRAT: rval = mkdirat(NUM(0), STR(1), (mode_t)NUM(2)); break; case ACTION_RMDIR: rval = rmdir(STR(0)); break; case ACTION_LINK: rval = link(STR(0), STR(1)); break; case ACTION_LINKAT: rval = linkat(NUM(0), STR(1), NUM(2), STR(3), (int)str2flags(linkat_flags, STR(4))); break; case ACTION_SYMLINK: rval = symlink(STR(0), STR(1)); break; case ACTION_SYMLINKAT: rval = symlinkat(STR(0), NUM(1), STR(2)); break; case ACTION_RENAME: rval = rename(STR(0), STR(1)); break; case ACTION_RENAMEAT: rval = renameat(NUM(0), STR(1), NUM(2), STR(3)); break; case ACTION_MKFIFO: rval = mkfifo(STR(0), (mode_t)NUM(1)); break; case ACTION_MKFIFOAT: rval = mkfifoat(NUM(0), STR(1), (mode_t)NUM(2)); break; case ACTION_MKNOD: case ACTION_MKNODAT: { mode_t ntype; dev_t dev; int fa; switch (scall->sd_action) { case ACTION_MKNOD: fa = 0; break; case ACTION_MKNODAT: fa = 1; break; default: abort(); } dev = makedev(NUM(fa + 3), NUM(fa + 4)); if (strcmp(STR(fa + 1), "c") == 0) /* character device */ ntype = S_IFCHR; else if (strcmp(STR(fa + 1), "b") == 0) /* block device */ ntype = S_IFBLK; else if (strcmp(STR(fa + 1), "f") == 0) /* fifo special */ ntype = S_IFIFO; else if (strcmp(STR(fa + 1), "d") == 0) /* directory */ ntype = S_IFDIR; else if (strcmp(STR(fa + 1), "o") == 0) /* regular file */ ntype = S_IFREG; else { fprintf(stderr, "wrong argument 1\n"); exit(1); } switch (scall->sd_action) { case ACTION_MKNOD: rval = mknod(STR(0), ntype | NUM(2), dev); break; case ACTION_MKNODAT: rval = mknodat(NUM(0), STR(1), ntype | NUM(3), dev); break; default: abort(); } break; } case ACTION_BIND: { struct sockaddr_un sunx; sunx.sun_family = AF_UNIX; strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1); sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; rval = socket(AF_UNIX, SOCK_STREAM, 0); if (rval < 0) break; rval = bind(rval, (struct sockaddr *)&sunx, sizeof(sunx)); break; } #ifdef HAS_BINDAT case ACTION_BINDAT: { struct sockaddr_un sunx; sunx.sun_family = AF_UNIX; strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1); sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; rval = socket(AF_UNIX, SOCK_STREAM, 0); if (rval < 0) break; rval = bindat(NUM(0), rval, (struct sockaddr *)&sunx, sizeof(sunx)); break; } #endif case ACTION_CONNECT: { struct sockaddr_un sunx; sunx.sun_family = AF_UNIX; strncpy(sunx.sun_path, STR(0), sizeof(sunx.sun_path) - 1); sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; rval = socket(AF_UNIX, SOCK_STREAM, 0); if (rval < 0) break; rval = connect(rval, (struct sockaddr *)&sunx, sizeof(sunx)); break; } #ifdef HAS_CONNECTAT case ACTION_CONNECTAT: { struct sockaddr_un sunx; sunx.sun_family = AF_UNIX; strncpy(sunx.sun_path, STR(1), sizeof(sunx.sun_path) - 1); sunx.sun_path[sizeof(sunx.sun_path) - 1] = '\0'; rval = socket(AF_UNIX, SOCK_STREAM, 0); if (rval < 0) break; rval = connectat(NUM(0), rval, (struct sockaddr *)&sunx, sizeof(sunx)); break; } #endif case ACTION_CHMOD: rval = chmod(STR(0), (mode_t)NUM(1)); break; case ACTION_FCHMOD: rval = fchmod(NUM(0), (mode_t)NUM(1)); break; #ifdef HAS_LCHMOD case ACTION_LCHMOD: rval = lchmod(STR(0), (mode_t)NUM(1)); break; #endif case ACTION_FCHMODAT: rval = fchmodat(NUM(0), STR(1), (mode_t)NUM(2), str2flags(fchmodat_flags, STR(3))); break; case ACTION_CHOWN: rval = chown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2)); break; case ACTION_FCHOWN: rval = fchown(NUM(0), (uid_t)NUM(1), (gid_t)NUM(2)); break; case ACTION_LCHOWN: rval = lchown(STR(0), (uid_t)NUM(1), (gid_t)NUM(2)); break; case ACTION_FCHOWNAT: rval = fchownat(NUM(0), STR(1), (uid_t)NUM(2), (gid_t)NUM(3), (int)str2flags(fchownat_flags, STR(4))); break; #ifdef HAS_CHFLAGS case ACTION_CHFLAGS: rval = chflags(STR(0), (unsigned long)str2flags(chflags_flags, STR(1))); break; #endif #ifdef HAS_FCHFLAGS case ACTION_FCHFLAGS: rval = fchflags(NUM(0), (unsigned long)str2flags(chflags_flags, STR(1))); break; #endif #ifdef HAS_CHFLAGSAT case ACTION_CHFLAGSAT: rval = chflagsat(NUM(0), STR(1), (unsigned long)str2flags(chflags_flags, STR(2)), (int)str2flags(chflagsat_flags, STR(3))); break; #endif #ifdef HAS_LCHFLAGS case ACTION_LCHFLAGS: rval = lchflags(STR(0), (unsigned long)str2flags(chflags_flags, STR(1))); break; #endif case ACTION_TRUNCATE: rval = truncate64(STR(0), NUM(1)); break; case ACTION_FTRUNCATE: rval = ftruncate64(NUM(0), NUM(1)); break; case ACTION_STAT: rval = stat64(STR(0), &sb); if (rval == 0) { show_stats(&sb, STR(1)); return (i); } break; case ACTION_FSTAT: rval = fstat64(NUM(0), &sb); if (rval == 0) { show_stats(&sb, STR(1)); return (i); } break; case ACTION_LSTAT: rval = lstat64(STR(0), &sb); if (rval == 0) { show_stats(&sb, STR(1)); return (i); } break; case ACTION_FSTATAT: rval = fstatat(NUM(0), STR(1), &sb, (int)str2flags(fstatat_flags, STR(2))); if (rval == 0) { show_stats(&sb, STR(3)); return (i); } break; case ACTION_PATHCONF: case ACTION_FPATHCONF: case ACTION_LPATHCONF: { long lrval; name = str2name(pathconf_names, STR(1)); if (name == -1) { fprintf(stderr, "unknown name %s", STR(1)); exit(1); } errno = 0; switch (scall->sd_action) { case ACTION_PATHCONF: lrval = pathconf(STR(0), name); break; case ACTION_FPATHCONF: lrval = fpathconf(NUM(0), name); break; case ACTION_LPATHCONF: lrval = lpathconf(STR(0), name); break; default: abort(); } if (lrval == -1 && errno == 0) { printf("unlimited\n"); return (i); } else if (lrval >= 0) { printf("%ld\n", lrval); return (i); } rval = -1; break; } #ifdef HAS_FREEBSD_ACL case ACTION_PREPENDACL: rval = -1; acl = acl_get_file(STR(0), ACL_TYPE_NFS4); if (acl == NULL) break; newacl = acl_from_text(STR(1)); if (acl == NULL) break; while (acl_get_entry(newacl, entry_id, &newentry) == 1) { entry_id = ACL_NEXT_ENTRY; if (acl_create_entry_np(&acl, &entry, 0)) break; if (acl_copy_entry(entry, newentry)) break; } rval = acl_set_file(STR(0), ACL_TYPE_NFS4, acl); break; case ACTION_READACL: acl = acl_get_file(STR(0), ACL_TYPE_NFS4); if (acl == NULL) rval = -1; else rval = 0; break; #endif case ACTION_WRITE: rval = write(NUM(0), STR(1), strlen(STR(1))); break; default: fprintf(stderr, "unsupported syscall\n"); exit(1); } #undef STR #undef NUM if (rval < 0) { const char *serrno; serrno = err2str(errno); fprintf(stderr, "%s returned %d\n", scall->sd_name, rval); printf("%s\n", serrno); exit(1); } printf("0\n"); return (i); }
/* * Try to work out the total size of all data by adding up the sizes of all * input files. If any of the input files are of indeterminate size (i.e. * they are a pipe), the total size is set to zero. * * Any files that cannot be stat()ed or that access() says we can't read * will cause a warning to be output and will be removed from the list. * * In line mode, any files that pass the above checks will then be read to * determine how many lines they contain, and the total size will be set to * the total line count. Only regular files will be read. */ void pv_calc_total_size(opts_t opts) { struct stat64 sb; int rc, i, j, fd; opts->size = 0; rc = 0; if (opts->argc < 1) { if (fstat64(STDIN_FILENO, &sb) == 0) opts->size = sb.st_size; return; } for (i = 0; i < opts->argc; i++) { if (strcmp(opts->argv[i], "-") == 0) { rc = fstat64(STDIN_FILENO, &sb); if (rc != 0) { opts->size = 0; return; } } else { rc = stat64(opts->argv[i], &sb); if (rc == 0) rc = access(opts->argv[i], R_OK); } if (rc != 0) { fprintf(stderr, "%s: %s: %s\n", opts->program_name, opts->argv[i], strerror(errno)); for (j = i; j < opts->argc - 1; j++) { opts->argv[j] = opts->argv[j + 1]; } opts->argc--; i--; opts->exit_status |= 2; continue; } if (S_ISBLK(sb.st_mode)) { /* * Get the size of block devices by opening * them and seeking to the end. */ if (strcmp(opts->argv[i], "-") == 0) { fd = open64("/dev/stdin", O_RDONLY); } else { fd = open64(opts->argv[i], O_RDONLY); } if (fd >= 0) { opts->size += lseek64(fd, 0, SEEK_END); close(fd); } else { fprintf(stderr, "%s: %s: %s\n", opts->program_name, opts->argv[i], strerror(errno)); opts->exit_status |= 2; } } else if (S_ISREG(sb.st_mode)) { opts->size += sb.st_size; } else { opts->size = 0; } } if (!opts->linemode) return; opts->size = 0; for (i = 0; i < opts->argc; i++) { fd = -1; if (strcmp(opts->argv[i], "-") == 0) { rc = fstat64(STDIN_FILENO, &sb); if ((rc != 0) || (!S_ISREG(sb.st_mode))) { opts->size = 0; return; } fd = dup(STDIN_FILENO); } else { rc = stat64(opts->argv[i], &sb); if ((rc != 0) || (!S_ISREG(sb.st_mode))) { opts->size = 0; return; } fd = open64(opts->argv[i], O_RDONLY); } if (fd < 0) { fprintf(stderr, "%s: %s: %s\n", opts->program_name, opts->argv[i], strerror(errno)); opts->size = 0; opts->exit_status |= 2; return; } while (1) { unsigned char scanbuf[1024]; /* RATS: ignore (OK) */ int numread, i; numread = read(fd, /* RATS: ignore (OK) */ scanbuf, sizeof(scanbuf)); if (numread < 0) { fprintf(stderr, "%s: %s: %s\n", opts->program_name, opts->argv[i], strerror(errno)); opts->exit_status |= 2; break; } else if (numread == 0) { break; } for (i = 0; i < numread; i++) { if (scanbuf[i] == '\n') opts->size++; } } lseek64(fd, 0, SEEK_SET); close(fd); } }
/* * Close the given file descriptor and open the next one, whose number in * the list is "filenum", returning the new file descriptor (or negative on * error). It is an error if the next input file is the same as the file * stdout is pointing to. */ int pv_next_file(opts_t opts, int filenum, int oldfd) { struct stat64 isb; struct stat64 osb; int fd; if (oldfd > 0) { if (close(oldfd)) { fprintf(stderr, "%s: %s: %s\n", opts->program_name, _("failed to close file"), strerror(errno)); opts->exit_status |= 8; return -1; } } if (filenum >= opts->argc) { opts->exit_status |= 8; return -1; } if (filenum < 0) { opts->exit_status |= 8; return -1; } if (strcmp(opts->argv[filenum], "-") == 0) { fd = STDIN_FILENO; } else { fd = open64(opts->argv[filenum], O_RDONLY); if (fd < 0) { fprintf(stderr, "%s: %s: %s: %s\n", opts->program_name, _("failed to read file"), opts->argv[filenum], strerror(errno)); opts->exit_status |= 2; return -1; } } if (fstat64(fd, &isb)) { fprintf(stderr, "%s: %s: %s: %s\n", opts->program_name, _("failed to stat file"), opts->argv[filenum], strerror(errno)); close(fd); opts->exit_status |= 2; return -1; } if (fstat64(STDOUT_FILENO, &osb)) { fprintf(stderr, "%s: %s: %s\n", opts->program_name, _("failed to stat output file"), strerror(errno)); close(fd); opts->exit_status |= 2; return -1; } /* * Check that this new input file is not the same as stdout's * destination. This restriction is ignored for anything other * than a regular file or block device. */ if (isb.st_dev != osb.st_dev) return fd; if (isb.st_ino != osb.st_ino) return fd; if (isatty(fd)) return fd; if ((!S_ISREG(isb.st_mode)) && (!S_ISBLK(isb.st_mode))) return fd; fprintf(stderr, "%s: %s: %s\n", opts->program_name, _("input file is output file"), opts->argv[filenum]); close(fd); opts->exit_status |= 4; return -1; }
int main (void) { const char *tmpdir; char *fname; int fd; FILE *fp; const char outstr[] = "hello world!\n"; char strbuf[sizeof outstr]; char buf[200]; struct stat64 st1; struct stat64 st2; int result = 0; tmpdir = getenv ("TMPDIR"); if (tmpdir == NULL || tmpdir[0] == '\0') tmpdir = "/tmp"; asprintf (&fname, "%s/tst-fseek.XXXXXX", tmpdir); if (fname == NULL) error (EXIT_FAILURE, errno, "cannot generate name for temporary file"); /* Create a temporary file. */ fd = mkstemp (fname); if (fd == -1) error (EXIT_FAILURE, errno, "cannot open temporary file"); fp = fdopen (fd, "w+"); if (fp == NULL) error (EXIT_FAILURE, errno, "cannot get FILE for temporary file"); setbuffer (fp, strbuf, sizeof (outstr) -1); if (fwrite (outstr, sizeof (outstr) - 1, 1, fp) != 1) { printf ("%d: write error\n", __LINE__); result = 1; goto out; } /* The EOF flag must be reset. */ if (fgetc (fp) != EOF) { printf ("%d: managed to read at end of file\n", __LINE__); result = 1; } else if (! feof (fp)) { printf ("%d: EOF flag not set\n", __LINE__); result = 1; } if (fseek (fp, 0, SEEK_CUR) != 0) { printf ("%d: fseek(fp, 0, SEEK_CUR) failed\n", __LINE__); result = 1; } else if (feof (fp)) { printf ("%d: fseek() didn't reset EOF flag\n", __LINE__); result = 1; } /* Do the same for fseeko(). */ if (fgetc (fp) != EOF) { printf ("%d: managed to read at end of file\n", __LINE__); result = 1; } else if (! feof (fp)) { printf ("%d: EOF flag not set\n", __LINE__); result = 1; } if (fseeko (fp, 0, SEEK_CUR) != 0) { printf ("%d: fseek(fp, 0, SEEK_CUR) failed\n", __LINE__); result = 1; } else if (feof (fp)) { printf ("%d: fseek() didn't reset EOF flag\n", __LINE__); result = 1; } /* Go back to the beginning of the file: absolute. */ if (fseek (fp, 0, SEEK_SET) != 0) { printf ("%d: fseek(fp, 0, SEEK_SET) failed\n", __LINE__); result = 1; } else if (fflush (fp) != 0) { printf ("%d: fflush() failed\n", __LINE__); result = 1; } else if (lseek (fd, 0, SEEK_CUR) != 0) { printf ("%d: lseek() returned different position\n", __LINE__); result = 1; } else if (fread (buf, sizeof (outstr) - 1, 1, fp) != 1) { printf ("%d: fread() failed\n", __LINE__); result = 1; } else if (memcmp (buf, outstr, sizeof (outstr) - 1) != 0) { printf ("%d: content after fseek(,,SEEK_SET) wrong\n", __LINE__); result = 1; } /* Now with fseeko. */ if (fseeko (fp, 0, SEEK_SET) != 0) { printf ("%d: fseeko(fp, 0, SEEK_SET) failed\n", __LINE__); result = 1; } else if (fflush (fp) != 0) { printf ("%d: fflush() failed\n", __LINE__); result = 1; } else if (lseek (fd, 0, SEEK_CUR) != 0) { printf ("%d: lseek() returned different position\n", __LINE__); result = 1; } else if (fread (buf, sizeof (outstr) - 1, 1, fp) != 1) { printf ("%d: fread() failed\n", __LINE__); result = 1; } else if (memcmp (buf, outstr, sizeof (outstr) - 1) != 0) { printf ("%d: content after fseeko(,,SEEK_SET) wrong\n", __LINE__); result = 1; } /* Go back to the beginning of the file: relative. */ if (fseek (fp, -((int) sizeof (outstr) - 1), SEEK_CUR) != 0) { printf ("%d: fseek(fp, 0, SEEK_SET) failed\n", __LINE__); result = 1; } else if (fflush (fp) != 0) { printf ("%d: fflush() failed\n", __LINE__); result = 1; } else if (lseek (fd, 0, SEEK_CUR) != 0) { printf ("%d: lseek() returned different position\n", __LINE__); result = 1; } else if (fread (buf, sizeof (outstr) - 1, 1, fp) != 1) { printf ("%d: fread() failed\n", __LINE__); result = 1; } else if (memcmp (buf, outstr, sizeof (outstr) - 1) != 0) { printf ("%d: content after fseek(,,SEEK_SET) wrong\n", __LINE__); result = 1; } /* Now with fseeko. */ if (fseeko (fp, -((int) sizeof (outstr) - 1), SEEK_CUR) != 0) { printf ("%d: fseeko(fp, 0, SEEK_SET) failed\n", __LINE__); result = 1; } else if (fflush (fp) != 0) { printf ("%d: fflush() failed\n", __LINE__); result = 1; } else if (lseek (fd, 0, SEEK_CUR) != 0) { printf ("%d: lseek() returned different position\n", __LINE__); result = 1; } else if (fread (buf, sizeof (outstr) - 1, 1, fp) != 1) { printf ("%d: fread() failed\n", __LINE__); result = 1; } else if (memcmp (buf, outstr, sizeof (outstr) - 1) != 0) { printf ("%d: content after fseeko(,,SEEK_SET) wrong\n", __LINE__); result = 1; } /* Go back to the beginning of the file: from the end. */ if (fseek (fp, -((int) sizeof (outstr) - 1), SEEK_END) != 0) { printf ("%d: fseek(fp, 0, SEEK_SET) failed\n", __LINE__); result = 1; } else if (fflush (fp) != 0) { printf ("%d: fflush() failed\n", __LINE__); result = 1; } else if (lseek (fd, 0, SEEK_CUR) != 0) { printf ("%d: lseek() returned different position\n", __LINE__); result = 1; } else if (fread (buf, sizeof (outstr) - 1, 1, fp) != 1) { printf ("%d: fread() failed\n", __LINE__); result = 1; } else if (memcmp (buf, outstr, sizeof (outstr) - 1) != 0) { printf ("%d: content after fseek(,,SEEK_SET) wrong\n", __LINE__); result = 1; } /* Now with fseeko. */ if (fseeko (fp, -((int) sizeof (outstr) - 1), SEEK_END) != 0) { printf ("%d: fseeko(fp, 0, SEEK_SET) failed\n", __LINE__); result = 1; } else if (fflush (fp) != 0) { printf ("%d: fflush() failed\n", __LINE__); result = 1; } else if (lseek (fd, 0, SEEK_CUR) != 0) { printf ("%d: lseek() returned different position\n", __LINE__); result = 1; } else if (fread (buf, sizeof (outstr) - 1, 1, fp) != 1) { printf ("%d: fread() failed\n", __LINE__); result = 1; } else if (memcmp (buf, outstr, sizeof (outstr) - 1) != 0) { printf ("%d: content after fseeko(,,SEEK_SET) wrong\n", __LINE__); result = 1; } if (fwrite (outstr, sizeof (outstr) - 1, 1, fp) != 1) { printf ("%d: write error 2\n", __LINE__); result = 1; goto out; } if (fwrite (outstr, sizeof (outstr) - 1, 1, fp) != 1) { printf ("%d: write error 3\n", __LINE__); result = 1; goto out; } if (fwrite (outstr, sizeof (outstr) - 1, 1, fp) != 1) { printf ("%d: write error 4\n", __LINE__); result = 1; goto out; } if (fwrite (outstr, sizeof (outstr) - 1, 1, fp) != 1) { printf ("%d: write error 5\n", __LINE__); result = 1; goto out; } if (fputc ('1', fp) == EOF || fputc ('2', fp) == EOF) { printf ("%d: cannot add characters at the end\n", __LINE__); result = 1; goto out; } /* Check the access time. */ if (fstat64 (fd, &st1) < 0) { printf ("%d: fstat64() before fseeko() failed\n\n", __LINE__); result = 1; } else { sleep (1); if (fseek (fp, -(2 + 2 * (sizeof (outstr) - 1)), SEEK_CUR) != 0) { printf ("%d: fseek() after write characters failed\n", __LINE__); result = 1; goto out; } else { time_t t; /* Make sure the timestamp actually can be different. */ sleep (1); t = time (NULL); if (fstat64 (fd, &st2) < 0) { printf ("%d: fstat64() after fseeko() failed\n\n", __LINE__); result = 1; } if (st1.st_ctime >= t) { printf ("%d: st_ctime not updated\n", __LINE__); result = 1; } if (st1.st_mtime >= t) { printf ("%d: st_mtime not updated\n", __LINE__); result = 1; } if (st1.st_ctime >= st2.st_ctime) { printf ("%d: st_ctime not changed\n", __LINE__); result = 1; } if (st1.st_mtime >= st2.st_mtime) { printf ("%d: st_mtime not changed\n", __LINE__); result = 1; } } } if (fread (buf, 1, 2 + 2 * (sizeof (outstr) - 1), fp) != 2 + 2 * (sizeof (outstr) - 1)) { printf ("%d: reading 2 records plus bits failed\n", __LINE__); result = 1; } else if (memcmp (buf, outstr, sizeof (outstr) - 1) != 0 || memcmp (&buf[sizeof (outstr) - 1], outstr, sizeof (outstr) - 1) != 0 || buf[2 * (sizeof (outstr) - 1)] != '1' || buf[2 * (sizeof (outstr) - 1) + 1] != '2') { printf ("%d: reading records failed\n", __LINE__); result = 1; } else if (ungetc ('9', fp) == EOF) { printf ("%d: ungetc() failed\n", __LINE__); result = 1; } else if (fseek (fp, -(2 + 2 * (sizeof (outstr) - 1)), SEEK_END) != 0) { printf ("%d: fseek after ungetc failed\n", __LINE__); result = 1; } else if (fread (buf, 1, 2 + 2 * (sizeof (outstr) - 1), fp) != 2 + 2 * (sizeof (outstr) - 1)) { printf ("%d: reading 2 records plus bits failed\n", __LINE__); result = 1; } else if (memcmp (buf, outstr, sizeof (outstr) - 1) != 0 || memcmp (&buf[sizeof (outstr) - 1], outstr, sizeof (outstr) - 1) != 0 || buf[2 * (sizeof (outstr) - 1)] != '1') { printf ("%d: reading records for the second time failed\n", __LINE__); result = 1; } else if (buf[2 * (sizeof (outstr) - 1) + 1] == '9') { printf ("%d: unget character not ignored\n", __LINE__); result = 1; } else if (buf[2 * (sizeof (outstr) - 1) + 1] != '2') { printf ("%d: unget somehow changed character\n", __LINE__); result = 1; } fclose (fp); fp = fopen (fname, "r"); if (fp == NULL) { printf ("%d: fopen() failed\n\n", __LINE__); result = 1; } else if (fstat64 (fileno (fp), &st1) < 0) { printf ("%d: fstat64() before fseeko() failed\n\n", __LINE__); result = 1; } else if (fseeko (fp, 0, SEEK_END) != 0) { printf ("%d: fseeko(fp, 0, SEEK_END) failed\n", __LINE__); result = 1; } else if (ftello (fp) != st1.st_size) { printf ("%d: fstat64 st_size %zd ftello %zd\n", __LINE__, (size_t) st1.st_size, (size_t) ftello (fp)); result = 1; } else printf ("%d: SEEK_END works\n", __LINE__); if (fp != NULL) fclose (fp); fp = fopen (fname, "r"); if (fp == NULL) { printf ("%d: fopen() failed\n\n", __LINE__); result = 1; } else if (fstat64 (fileno (fp), &st1) < 0) { printf ("%d: fstat64() before fgetc() failed\n\n", __LINE__); result = 1; } else if (fgetc (fp) == EOF) { printf ("%d: fgetc() before fseeko() failed\n\n", __LINE__); result = 1; } else if (fseeko (fp, 0, SEEK_END) != 0) { printf ("%d: fseeko(fp, 0, SEEK_END) failed\n", __LINE__); result = 1; } else if (ftello (fp) != st1.st_size) { printf ("%d: fstat64 st_size %zd ftello %zd\n", __LINE__, (size_t) st1.st_size, (size_t) ftello (fp)); result = 1; } else printf ("%d: SEEK_END works\n", __LINE__); if (fp != NULL) fclose (fp); out: unlink (fname); return result; }
static int do_test (void) { /* fdopendir takes over the descriptor, make a copy. */ int dupfd = dup (dir_fd); if (dupfd == -1) { puts ("dup failed"); return 1; } if (lseek (dupfd, 0, SEEK_SET) != 0) { puts ("1st lseek failed"); return 1; } /* The directory should be empty safe the . and .. files. */ DIR *dir = fdopendir (dupfd); if (dir == NULL) { puts ("fdopendir failed"); return 1; } struct dirent64 *d; while ((d = readdir64 (dir)) != NULL) if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0) { printf ("temp directory contains file \"%s\"\n", d->d_name); return 1; } closedir (dir); /* Try to create a file. */ int fd = openat (dir_fd, "some-file", O_CREAT|O_RDWR|O_EXCL, 0666); if (fd == -1) { if (errno == ENOSYS) { puts ("*at functions not supported"); return 0; } puts ("file creation failed"); return 1; } write (fd, "hello", 5); puts ("file created"); struct stat64 st1; if (fstat64 (fd, &st1) != 0) { puts ("fstat64 failed"); return 1; } close (fd); if (linkat (dir_fd, "some-file", dir_fd, "another-file", 0) != 0) { puts ("symlinkat failed"); return 1; } struct stat64 st2; if (fstatat64 (dir_fd, "some-file", &st2, 0) != 0) { puts ("fstatat64 failed"); return 1; } if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) { puts ("file changed after symlinkat"); return 1; } if (fstatat64 (dir_fd, "another-file", &st2, AT_SYMLINK_NOFOLLOW) != 0) { puts ("2nd fstatat64 failed"); return 1; } if (S_ISLNK (st2.st_mode)) { puts ("2nd fstatat64 shows file is a symlink"); return 1; } if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino || st1.st_size != st2.st_size) { puts ("stat results for linked file do not match"); return 1; } if (fstatat64 (dir_fd, "another-file", &st2, 0) != 0) { puts ("3rd fstatat64 failed"); return 1; } if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino || st1.st_size != st2.st_size) { puts ("stat results do not match"); return 1; } if (unlinkat (dir_fd, "another-file", 0) != 0) { puts ("unlinkat failed"); return 1; } if (unlinkat (dir_fd, "some-file", 0) != 0) { puts ("2nd unlinkat failed"); return 1; } close (dir_fd); return 0; }
/* * load a message catalog which specified with current locale, * and catalog name. */ static struct db_info * load_db(const char *curloc, const char *catname, int *err) { char pathname[PATH_MAX]; struct stat64 sb; caddr_t addr; struct db_info *db; int fd; int i; *err = 0; /* First time called, allocate space */ if (!db_info) { if ((db_info = libc_malloc(MINDB * sizeof (struct db_info))) == NULL) { *err = 1; return (NULL); } maxdb = MINDB; } for (i = 0; i < db_count; i++) { if (db_info[i].flag == 0) break; } /* New catalogue */ if (i == db_count) { if (db_count == maxdb) { if ((db = libc_realloc(db_info, ++maxdb * sizeof (struct db_info))) == NULL) { *err = 1; return (NULL); } db_info = db; } db_count++; } db = &db_info[i]; db->flag = 0; (void) strcpy(db->db_name, catname); db->saved_locale = libc_strdup(curloc); if (db->saved_locale == NULL) { *err = 1; return (NULL); } db->flag = DB_OPEN; if (snprintf(pathname, sizeof (pathname), _DFLT_LOC_PATH "%s" MESSAGES "%s", db->saved_locale, db->db_name) >= sizeof (pathname)) { /* * We won't set err here, because an invalid locale is not * the fatal condition, but we can fall back to "C" * locale. */ return (NULL); } if ((fd = open(pathname, O_RDONLY)) != -1 && fstat64(fd, &sb) != -1 && (addr = mmap(0, (size_t)sb.st_size, PROT_READ, MAP_SHARED, fd, 0)) != MAP_FAILED) { db->flag |= DB_EXIST; db->addr = (uintptr_t)addr; db->length = (size_t)sb.st_size; } if (fd != -1) (void) close(fd); return (db); }
#define RESTARTABLE(_cmd, _result) do { \ do { \ _result = _cmd; \ } while ((_result == -1) && (errno == EINTR)); \ } while(0) JNIEXPORT void JNICALL Java_sun_nio_ch_FileKey_initIDs(JNIEnv *env, jclass clazz) { key_st_dev = (*env)->GetFieldID(env, clazz, "st_dev", "J"); key_st_ino = (*env)->GetFieldID(env, clazz, "st_ino", "J"); } JNIEXPORT void JNICALL Java_sun_nio_ch_FileKey_init(JNIEnv *env, jobject this, jobject fdo) { struct stat64 fbuf; int res; RESTARTABLE(fstat64(fdval(env, fdo), &fbuf), res); if (res < 0) { JNU_ThrowIOExceptionWithLastError(env, "fstat64 failed"); } else { (*env)->SetLongField(env, this, key_st_dev, (jlong)fbuf.st_dev); (*env)->SetLongField(env, this, key_st_ino, (jlong)fbuf.st_ino); } }
struct store *newfstore(char *dir) { struct store *st; struct fstore *fst; char tbuf[1024]; struct loghdr lh; struct idxhdr ih; struct stat64 sb; fst = calloc(1, sizeof(*fst)); fst->logfd = -1; fst->idxfd = -1; snprintf(tbuf, sizeof(tbuf), "%s/log", dir); if((fst->logfd = open(tbuf, O_RDWR | O_LARGEFILE)) < 0) { flog(LOG_ERR, "could not open log %s: %s", tbuf, strerror(errno)); release(fst); return(NULL); } if(fstat64(fst->logfd, &sb)) { flog(LOG_ERR, "could not stat log: %s", strerror(errno)); release(fst); return(NULL); } fst->logsize = sb.st_size; if(readall(fst->logfd, &lh, sizeof(lh), 0)) { flog(LOG_ERR, "could not read log header: %s", strerror(errno)); release(fst); return(NULL); } if(memcmp(lh.magic, LOGMAGIC, sizeof(LOGMAGIC))) { flog(LOG_ERR, "invalid log magic"); release(fst); return(NULL); } snprintf(tbuf, sizeof(tbuf), "%s/index", dir); if((fst->idxfd = open(tbuf, O_RDWR | O_LARGEFILE)) < 0) { flog(LOG_ERR, "could not open index %s: %s", tbuf, strerror(errno)); release(fst); return(NULL); } if(fstat64(fst->idxfd, &sb)) { flog(LOG_ERR, "could not stat index: %s", strerror(errno)); release(fst); return(NULL); } if(readall(fst->idxfd, &ih, sizeof(ih), 0)) { flog(LOG_ERR, "could not read index header: %s", strerror(errno)); release(fst); return(NULL); } if(memcmp(ih.magic, IDXMAGIC, sizeof(IDXMAGIC))) { flog(LOG_ERR, "invalid index magic"); release(fst); return(NULL); } if(sb.st_size != (sizeof(struct idxhdr) + ih.size * sizeof(struct idxent))) { flog(LOG_ERR, "invalid index size"); release(fst); return(NULL); } fst->idxsize = ih.size; st = newstore(&fstops); st->pdata = fst; return(st); }
int main(int argc, char *argv[]) { char *progname; int fd; int c; extern char *optarg; unsigned nprocs = 0; unsigned procno; pid_t *pidarray=NULL; pid_t pid; pid_t wr_pid = 0; uchar_t *buf=NULL; unsigned int seed; int pagesize = sysconf(_SC_PAGE_SIZE); int alarmtime = 0; struct sigaction sa; unsigned i; int write_cnt; uchar_t data; int no_prob = 0; int wait_stat; time_t t; #ifdef LARGE_FILE off64_t bytes_left; #else /* LARGE_FILE */ off_t bytes_left; #endif /* LARGE_FILE */ progname = *argv; tst_tmpdir(); if (argc < 2) { (void)fprintf(stderr, "usage: %s %s\n", progname, usage); exit(1); } while ((c = getopt(argc, argv, "S:omdlrf:p:t:w:s:")) != -1) { switch (c) { case 'd': debug = 1; break; case 't': alarmtime = atoi(optarg) * 60; break; case 'p': nprocs = atoi(optarg); break; case 'l': leavefile = 1; break; case 's': sleeptime = atoi(optarg); if (sleeptime < 0) { (void)fprintf(stderr, "error: negative " "sleeptime\n"); anyfail(); } break; case 'w': growsize = atoi(optarg); if (growsize < 0) { (void)fprintf(stderr, "error: negative write " "size\n"); anyfail(); } break; case 'f': #ifdef LARGE_FILE filesize = atoll(optarg); #else /* LARGE_FILE */ filesize = atoi(optarg); #endif /* LARGE_FILE */ if (filesize < 0) { (void)fprintf(stderr, "error: negative " "filesize\n"); anyfail(); } break; case 'r': randloops = 1; break; case 'm': dosync = 1; break; case 'o': do_offset = 1; break; case 'S': #ifdef LARGE_FILE sparseoffset = atoll(optarg); #else /* LARGE_FILE */ sparseoffset = atoi(optarg); #endif /* LARGE_FILE */ if (sparseoffset % pagesize != 0) { fprintf(stderr, "sparseoffset must be pagesize multiple\n"); anyfail(); } break; default: (void)fprintf(stderr, "usage: %s %s\n", progname, usage); anyfail(); } } if (nprocs > 255) { (void)fprintf(stderr, "invalid nprocs %d - (range 0-255)\n", nprocs); anyfail(); } (void)time(&t); //(void)printf("%s: Started %s", argv[0], ctime(&t)); LTP Port (void)sprintf(filename, "%sout.%d", progname, getpid()); seed = initrand(); pattern = seed & 0xff; if (debug) { #ifdef LARGE_FILE (void)printf("creating file <%s> with %Ld bytes, pattern %d\n", filename, filesize, pattern); #else /* LARGE_FILE */ (void)printf("creating file <%s> with %ld bytes, pattern %d\n", filename, filesize, pattern); #endif /* LARGE_FILE */ if (alarmtime) (void)printf("running for %d minutes\n", alarmtime/60); else (void)printf("running with no time limit\n"); } /* * Plan for death by signal. User may have specified * a time limit, in which case set an alarm and catch SIGALRM. * Also catch and cleanup with SIGINT, SIGQUIT, and SIGTERM. */ sa.sa_handler = finish; sa.sa_flags = 0; if (sigemptyset(&sa.sa_mask)) { perror("sigempty error"); goto cleanup; } if (sigaction(SIGINT, &sa, 0) == -1) { perror("sigaction error SIGINT"); goto cleanup; } if (alarmtime) { if (sigaction(SIGALRM, &sa, 0) == -1) { perror("sigaction error"); goto cleanup; } (void)alarm(alarmtime); } /* If we get a SIGQUIT or SIGTERM, clean up and exit immediately. */ sa.sa_handler = clean_up_file; if (sigaction(SIGQUIT, &sa, 0) == -1) { perror("sigaction error SIGQUIT"); goto cleanup; } if (sigaction(SIGTERM, &sa, 0) == -1) { perror("sigaction error SIGTERM"); goto cleanup; } #ifdef LARGE_FILE if ((fd = open64(filename, O_CREAT|O_TRUNC|O_RDWR, 0664)) == -1) { #else /* LARGE_FILE */ if ((fd = open(filename, O_CREAT|O_TRUNC|O_RDWR, 0664)) == -1) { #endif /* LARGE_FILE */ perror("open error"); anyfail(); } if ((buf = (uchar_t *)malloc(pagesize+growsize)) == NULL || (pidarray = (pid_t *)malloc(nprocs*sizeof(pid_t))) == NULL) { perror("malloc error"); anyfail(); } for (i = 0; i < nprocs; i++) *(pidarray+i) = 0; for (i = 0, data = 0; i < pagesize; i++) { *(buf+i) = (data + pattern) & 0xff; if (++data == nprocs) data = 0; } for (data = 0; i < pagesize+growsize; i++) { *(buf+i) = (data + pattern) & 0xff; if (++data == nprocs) data = 0; } #ifdef LARGE_FILE if (lseek64(fd, sparseoffset, SEEK_SET) < 0) { #else /* LARGE_FILE */ if (lseek(fd, sparseoffset, SEEK_SET) < 0) { #endif /* LARGE_FILE */ perror("lseek"); anyfail(); } for (bytes_left = filesize; bytes_left; bytes_left -= c) { write_cnt = min(pagesize, bytes_left); if ((c = write(fd, (char *)buf, write_cnt)) != write_cnt) { if (c == -1) { perror("write error"); } else { (void)fprintf(stderr, "write: wrote %d of %d " "bytes\n", c, write_cnt); } (void)close(fd); (void)unlink(filename); anyfail(); } } (void)close(fd); /* * Fork off mmap children. */ for (procno = 0; procno < nprocs; procno++) { switch (pid = fork()) { case -1: perror("fork error"); goto cleanup; case 0: child_mapper(filename, procno, nprocs); exit(0); default: pidarray[procno] = pid; } } /* * Now fork off an additional process to continually * write to (and grow) the file. */ if ((wr_pid = fork()) == -1) { perror("fork error"); goto cleanup; } else if (wr_pid == 0) { /* child */ child_writer(filename, buf); exit(0); } /* * Now wait for children and refork them as needed. */ while (!finished) { pid = wait(&wait_stat); /* * Block signals while processing child exit. */ if (sighold(SIGALRM) || sighold(SIGINT)) { perror("sighold error"); goto cleanup; } if (pid != -1) { /* * Check exit status, then refork with the * appropriate procno. */ if (!WIFEXITED(wait_stat) || WEXITSTATUS(wait_stat) != 0) { (void)fprintf(stderr, "child exit with err " "<x%x>\n", wait_stat); goto cleanup; } for (i = 0; i < nprocs; i++) if (pid == pidarray[i]) break; if (i == nprocs) { if (pid == wr_pid) { (void)fprintf(stderr, "writer child unexpected exit <x%x>\n", wait_stat); wr_pid = 0; } else (void)fprintf(stderr, "unknown child " "pid %d, <x%x>\n", pid, wait_stat); goto cleanup; } if ((pid = fork()) == -1) { perror("fork error"); pidarray[i] = 0; goto cleanup; } else if (pid == 0) { /* child */ child_mapper(filename, i, nprocs); exit(0); } else pidarray[i] = pid; } else { /* * wait returned an error. If EINTR, then * normal finish, else it's an unexpected * error... */ if (errno != EINTR || !finished) { perror("unexpected wait error"); goto cleanup; } } if (sigrelse(SIGALRM) || sigrelse(SIGINT)) { perror("sigrelse error"); goto cleanup; } } /* * Finished! Check the file for sanity, then kill all * the children and done!. */ (void)alarm(0); no_prob = 1; cleanup: for (i = 0; i < nprocs; i++) (void)kill(pidarray[i], SIGKILL); (void)kill(wr_pid, SIGKILL); while (wait(&wait_stat) != -1 || errno != ECHILD) continue; if (no_prob) { /* only check file if no errors */ if (!fileokay(filename, buf)) { (void)fprintf(stderr, "file data incorrect!\n"); (void)printf(" leaving file <%s>\n", filename); anyfail(); } else { (void)printf("file data okay\n"); if (!leavefile) (void)unlink(filename); } } else (void)printf(" leaving file <%s>\n", filename); (void)time(&t); // (void)printf("%s: Finished %s", argv[0], ctime(&t)); LTP Port ok_exit(); return 0; } /* * Child process that reads/writes map. The child stats the file * to determine the size, maps the size of the file, then reads/writes * its own locations on random pages of the map (its locations being * determined based on nprocs & procno). After a specific number of * iterations, it exits. */ void child_mapper(char *file, unsigned procno, unsigned nprocs) { #ifdef LARGE_FILE struct stat64 statbuf; off64_t filesize; off64_t offset; #else /* LARGE_FILE */ struct stat statbuf; off_t filesize; off_t offset; #endif /* LARGE_FILE */ size_t validsize; size_t mapsize; caddr_t maddr, paddr; int fd; int pagesize = sysconf(_SC_PAGE_SIZE); unsigned randpage; unsigned int seed; unsigned loopcnt; unsigned nloops; unsigned mappages; unsigned mapflags; unsigned i; mapflags = MAP_SHARED; seed = initrand(); /* initialize random seed */ #ifdef LARGE_FILE if ((fd = open64(file, O_RDWR)) == -1) { #else /* LARGE_FILE */ if ((fd = open(file, O_RDWR)) == -1) { #endif /* LARGE_FILE */ perror("open error"); anyfail(); } #ifdef LARGE_FILE if (fstat64(fd, &statbuf) == -1) { #else /* LARGE_FILE */ if (fstat(fd, &statbuf) == -1) { #endif /* LARGE_FILE */ perror("stat error"); anyfail(); } filesize = statbuf.st_size; if (statbuf.st_size - sparseoffset > SIZE_MAX) { fprintf(stderr, "size_t overflow when setting up map\n"); anyfail(); } mapsize = (size_t)(statbuf.st_size - sparseoffset); mappages = roundup(mapsize, pagesize) / pagesize; offset = sparseoffset; if (do_offset) { int pageoffset = lrand48() % mappages; int byteoffset = pageoffset * pagesize; offset += byteoffset; mapsize -= byteoffset; mappages -= pageoffset; } #ifdef LARGE_FILE if ((maddr = mmap64(0, mapsize, PROT_READ|PROT_WRITE, mapflags, fd, offset)) == (caddr_t)-1) { #else /* LARGE_FILE */ if ((maddr = mmap(0, mapsize, PROT_READ|PROT_WRITE, mapflags, fd, offset)) == (caddr_t)-1) { #endif /* LARGE_FILE */ perror("mmap error"); anyfail(); } (void)close(fd); nloops = (randloops) ? (lrand48() % MAXLOOPS) : MAXLOOPS; if (debug) { #ifdef LARGE_FILE (void)printf("child %d (pid %ld): seed %d, fsize %Ld, " "mapsize %d, off %Ld, loop %d\n", procno, getpid(), seed, filesize, mapsize, offset/pagesize, nloops); #else /* LARGE_FILE */ (void)printf("child %d (pid %d): seed %d, fsize %ld, " "mapsize %ld, off %ld, loop %d\n", procno, getpid(), seed, filesize, (long)mapsize, offset/pagesize, nloops); #endif /* LARGE_FILE */ } /* * Now loop read/writing random pages. */ for (loopcnt = 0; loopcnt < nloops; loopcnt++) { randpage = lrand48() % mappages; paddr = maddr + (randpage * pagesize); /* page address */ if (randpage < mappages - 1 || !(mapsize % pagesize)) validsize = pagesize; else validsize = mapsize % pagesize; /* * Because one child is mapping file in extend mode, * it may be padded with zeros at end. So we can't * do an exact check -- accept known pattern OR zeros. */ for (i = procno; i < validsize; i += nprocs) { if (*((unsigned char *)(paddr+i)) != ((procno + pattern) & 0xff) && *((unsigned char *)(paddr+i)) != 0) { (void)fprintf(stderr, "child %d: invalid data " "<x%x>", procno, *((unsigned char *)(paddr+i))); (void)fprintf(stderr, " at pg %d off %d, exp " "<x%x>\n", randpage, i, (procno+pattern)&0xff); anyfail(); } /* * Now write it. */ *(paddr+i) = (procno + pattern) & 0xff; } } if (dosync) { /* * Exercise msync() as well! */ randpage = lrand48() % mappages; paddr = maddr + (randpage * pagesize); /* page address */ if (msync(paddr, (mappages - randpage)*pagesize, MS_SYNC) == -1) { perror("msync error"); anyfail(); } } exit(0); } /* * child_writer * The child process that continually (and slowly!!) grows * the file. The purpose of this is to exercise the code * supporting mapping of fragments. The map children are * constantly reforking and will pick up the map changes, etc. * This process executes until signalled (i.e. has no exit!) * unless error. */ void child_writer(char *file, uchar_t *buf) /* buf already set up in main */ { int fd; #ifdef LARGE_FILE struct stat64 statbuf; off64_t off; #else /* LARGE_FILE */ struct stat statbuf; off_t off; #endif /* LARGE_FILE */ int pagesize = sysconf(_SC_PAGE_SIZE); uchar_t *p; int cnt; #ifdef LARGE_FILE if ((fd = open64(file, O_RDWR)) == -1) { #else /* LARGE_FILE */ if ((fd = open(file, O_RDWR)) == -1) { #endif /* LARGE_FILE */ perror("open error"); anyfail(); } #ifdef LARGE_FILE if ((off = lseek64(fd, 0, SEEK_END)) == -1) { #else /* LARGE_FILE */ if ((off = lseek(fd, 0, SEEK_END)) == -1) { #endif /* LARGE_FILE */ perror("lseek error"); anyfail(); } for (;;) { #ifdef LARGE_FILE if (fstat64(fd, &statbuf) == -1) { #else /* LARGE_FILE */ if (fstat(fd, &statbuf) == -1) { #endif /* LARGE_FILE */ perror("fstat error"); anyfail(); } #ifdef LARGE_FILE if (debug) (void)printf("writer %d bytes at off %Ld, size %Ld\n", growsize, off, statbuf.st_size); #else /* LARGE_FILE */ if (debug) (void)printf("writer %d bytes at off %ld, size %ld\n", growsize, off, statbuf.st_size); #endif /* LARGE_FILE */ /* * Write some number of bytes, then sleep some * number of seconds... * Need to keep track of our offset so write the * right bytes. */ p = buf + (off % pagesize); if ((cnt = write(fd, p, growsize)) != growsize) { if (cnt == -1) perror("write error"); else (void)fprintf(stderr, "wrote %d of %d bytes\n", cnt, growsize); anyfail(); } off += growsize; (void)sleep(sleeptime); if (dosync) { if (fsync(fd) == -1) { perror("fsync error"); anyfail(); } } } } /* * Make sure file has all the correct data. */ int fileokay(char *file, uchar_t *expbuf) { #ifdef LARGE_FILE struct stat64 statbuf; #else /* LARGE_FILE */ struct stat statbuf; #endif /* LARGE_FILE */ size_t mapsize; uchar_t *readbuf; unsigned mappages; unsigned pagesize = sysconf(_SC_PAGE_SIZE); int fd; int cnt; unsigned i, j; #ifdef LARGE_FILE if ((fd = open64(file, O_RDONLY)) == -1) { #else /* LARGE_FILE */ if ((fd = open(file, O_RDONLY)) == -1) { #endif /* LARGE_FILE */ perror("open error"); anyfail(); } #ifdef LARGE_FILE if (fstat64(fd, &statbuf) == -1) { #else /* LARGE_FILE */ if (fstat(fd, &statbuf) == -1) { #endif /* LARGE_FILE */ perror("stat error"); anyfail(); } #ifdef LARGE_FILE if (lseek64(fd, sparseoffset, SEEK_SET) < 0) { #else /* LARGE_FILE */ if (lseek(fd, sparseoffset, SEEK_SET) < 0) { #endif /* LARGE_FILE */ perror("lseek"); exit(1); } readbuf = (uchar_t *)malloc(pagesize); if (statbuf.st_size - sparseoffset > SIZE_MAX) { fprintf(stderr, "size_t overflow when setting up map\n"); exit(1); } mapsize = (size_t)(statbuf.st_size - sparseoffset); mappages = roundup(mapsize, pagesize) / pagesize; for (i = 0; i < mappages; i++) { cnt = read(fd, (char *)readbuf, pagesize); if (cnt == -1) { perror("read error"); return(0); } else if (cnt != pagesize) { /* * Okay if at last page in file... */ if ((i * pagesize) + cnt != mapsize) { (void)fprintf(stderr, "read %d of %ld bytes\n", (i*pagesize)+cnt, (long)mapsize); return(0); } } /* * Compare read bytes of data. * May have zeros from map extend... */ for (j = 0; j < cnt; j++) { if (expbuf[j] != readbuf[j] && readbuf[j] != 0) { (void)fprintf(stderr, "read bad data: exp %c got %c", expbuf[j], readbuf[j]); #ifdef LARGE_FILE (void)fprintf(stderr, ", pg %d off %d, " "(fsize %Ld)\n", i, j, statbuf.st_size); #else /* LARGE_FILE */ (void)fprintf(stderr, ", pg %d off %d, " "(fsize %ld)\n", i, j, statbuf.st_size); #endif /* LARGE_FILE */ return(0); } } } return(1); } /*ARGSUSED*/ void finish(int sig) { finished++; /* finish nicely and check the file contents */ } /*ARGSUSED*/ void clean_up_file(int sig) { if (!leavefile) (void)unlink(filename); exit(1); } unsigned int initrand(void) { unsigned int seed; /* * Initialize random seed... Got this from a test written * by scooter: * Use srand/rand to diffuse the information from the * time and pid. If you start several processes, then * the time and pid information don't provide much * variation. */ srand((unsigned int)getpid()); seed = rand(); srand((unsigned int)time((time_t *)0)); seed = (seed ^ rand()) % 100000; srand48((long int)seed); return (seed); } /***** LTP Port *****/ void ok_exit() { tst_resm(TPASS, "Test passed\n"); tst_rmdir(); tst_exit(); } int anyfail() { tst_resm(TFAIL, "Test failed\n"); tst_rmdir(); tst_exit(); return(0); }
static void zpool_open_func(void *arg) { rdsk_node_t *rn = arg; #ifdef __APPLE__ struct stat statbuf; #else struct stat64 statbuf; #endif nvlist_t *config; int num_labels; int fd; if (rn->rn_nozpool) return; #if defined (__linux__) || defined (__APPLE__) /* * Skip devices with well known prefixes there can be side effects * when opening devices which need to be avoided. * * core - Symlink to /proc/kcore * fd* - Floppy interface. * fuse - Fuse control device. * hpet - High Precision Event Timer * lp* - Printer interface. * parport* - Parallel port interface. * ppp - Generic PPP driver. * random - Random device * rtc - Real Time Clock * tty* - Generic serial interface. * urandom - Random device. * usbmon* - USB IO monitor. * vcs* - Virtual console memory. * watchdog - Watchdog must be closed in a special way. */ if ((strncmp(rn->rn_name, "core", 4) == 0) || (strncmp(rn->rn_name, "fd", 2) == 0) || (strncmp(rn->rn_name, "fuse", 4) == 0) || (strncmp(rn->rn_name, "hpet", 4) == 0) || (strncmp(rn->rn_name, "lp", 2) == 0) || (strncmp(rn->rn_name, "parport", 7) == 0) || (strncmp(rn->rn_name, "ppp", 3) == 0) || (strncmp(rn->rn_name, "random", 6) == 0) || (strncmp(rn->rn_name, "rtc", 3) == 0) || (strncmp(rn->rn_name, "tty", 3) == 0) || (strncmp(rn->rn_name, "urandom", 7) == 0) || (strncmp(rn->rn_name, "usbmon", 6) == 0) || (strncmp(rn->rn_name, "vcs", 3) == 0) || #ifdef __APPLE__ (strncmp(rn->rn_name, "pty", 3) == 0) || // lots, skip for speed (strncmp(rn->rn_name, "com", 3) == 0) || // /dev/com_digidesign_semiface #endif (strncmp(rn->rn_name, "watchdog", 8) == 0)) return; /* * Ignore failed stats. We only want regular files and block devices. */ if (fstatat64(rn->rn_dfd, rn->rn_name, &statbuf, 0) != 0 || (!S_ISREG(statbuf.st_mode) && !S_ISBLK(statbuf.st_mode))) return; #ifdef __APPLE__ /* It is desirable to skip optical media as well, as they are * also called /dev/diskX */ if (is_optical_media((char *)rn->rn_name)) return; #endif if ((fd = openat64(rn->rn_dfd, rn->rn_name, O_RDONLY)) < 0) { /* symlink to a device that's no longer there */ if (errno == ENOENT) nozpool_all_slices(rn->rn_avl, rn->rn_name); return; } #else /* LINUX, APPLE -> IllumOS */ if ((fd = openat64(rn->rn_dfd, rn->rn_name, O_RDONLY)) < 0) { /* symlink to a device that's no longer there */ if (errno == ENOENT) nozpool_all_slices(rn->rn_avl, rn->rn_name); return; } /* * Ignore failed stats. We only want regular * files, character devs and block devs. */ if (fstat64(fd, &statbuf) != 0 || (!S_ISREG(statbuf.st_mode) && !S_ISCHR(statbuf.st_mode) && !S_ISBLK(statbuf.st_mode))) { (void) close(fd); return; } #endif /* this file is too small to hold a zpool */ if (S_ISREG(statbuf.st_mode) && statbuf.st_size < SPA_MINDEVSIZE) { (void) close(fd); return; } else if (!S_ISREG(statbuf.st_mode)) { /* * Try to read the disk label first so we don't have to * open a bunch of minor nodes that can't have a zpool. */ check_slices(rn->rn_avl, fd, rn->rn_name); } #ifdef __APPLE__ int32_t blksz = 0; if (S_ISBLK(statbuf.st_mode) && (ioctl(fd, DKIOCGETBLOCKSIZE, &blksz) || blksz == 0)) { if (strncmp(rn->rn_name, "vn", 2) != 0) fprintf(stderr, "device '%s' failed to report blocksize -- skipping\r\n", rn->rn_name); close(fd); return; } struct sigaction sact; sigemptyset(&sact.sa_mask); sact.sa_flags = 0; sact.sa_handler = signal_alarm; sigaction(SIGALRM, &sact, NULL); if (setjmp(buffer) != 0) { printf("ZFS: Warning, timeout reading device '%s'\n", rn->rn_name); close(fd); return; } alarm(20); #endif if ((zpool_read_label(fd, &config, &num_labels)) != 0) { #ifdef __APPLE__ alarm(0); #endif (void) close(fd); (void) no_memory(rn->rn_hdl); return; } #ifdef __APPLE__ alarm(0); #endif if (num_labels == 0) { (void) close(fd); nvlist_free(config); return; } (void) close(fd); rn->rn_config = config; rn->rn_num_labels = num_labels; }
int get_devinfo(struct s_devinfo *outdev, char *indevname, int min, int maj) { char sysblkdevname[512]; blkid_tag_iterate iter; char sysblkinfo[PATH_MAX]; const char *type, *value; struct stat64 statbuf; struct dirent *dir; char temp[PATH_MAX]; blkid_dev dev; DIR *dirdesc; FILE *finfo; int found; int fd; int i; // init memset(outdev, 0, sizeof(struct s_devinfo)); // defaults values outdev->devtype=BLKDEV_INVALID; snprintf(outdev->label, sizeof(outdev->label), "<unknown>"); snprintf(outdev->uuid, sizeof(outdev->uuid), "<unknown>"); snprintf(outdev->fsname, sizeof(outdev->fsname), "<unknown>"); // check the name starts with "/dev/" if ((strlen(indevname) < 5) || (memcmp(indevname, "/dev/", 5)!=0)) return -1; // get short name ("/dev/sda1" -> "sda1") snprintf(outdev->devname, sizeof(outdev->devname), "%s", indevname+5); // skip "/dev/" // get long name if there is one (eg: LVM / devmapper) snprintf(outdev->longname, sizeof(outdev->longname), "%s", indevname); if ((dirdesc=opendir("/dev/mapper"))!=NULL) { found=false; while (((dir=readdir(dirdesc)) != NULL) && found==false) { snprintf(temp, sizeof(temp), "/dev/mapper/%s", dir->d_name); if ((stat64(temp, &statbuf)==0) && S_ISBLK(statbuf.st_mode) && (major(statbuf.st_rdev)==maj) && (minor(statbuf.st_rdev)==min)) { snprintf(outdev->longname, sizeof(outdev->longname), "%s", temp); found=true; } } closedir(dirdesc); } // get device basic info (size, major, minor) if (((fd=open64(outdev->longname, O_RDONLY|O_LARGEFILE))<0) || ((outdev->devsize=lseek64(fd, 0, SEEK_END))<0) || (fstat64(fd, &statbuf)!=0) || (!S_ISBLK(statbuf.st_mode)) || (close(fd)<0)) return -1; outdev->rdev=statbuf.st_rdev; outdev->major=major(statbuf.st_rdev); outdev->minor=minor(statbuf.st_rdev); format_size(outdev->devsize, outdev->txtsize, sizeof(outdev->txtsize), 'h'); if (outdev->devsize==1024) // ignore extended partitions return -1; // devname shown in /sys/block (eg for HP-cciss: "cciss/c0d0" -> "cciss!c0d0") snprintf(sysblkdevname, sizeof(sysblkdevname), "%s", outdev->devname); for (i=0; (sysblkdevname[i]!=0) && (i<sizeof(sysblkdevname)); i++) if (sysblkdevname[i]=='/') sysblkdevname[i]='!'; // check if it's a physical disk (there is a "/sys/block/${devname}/device") snprintf(sysblkinfo, sizeof(sysblkinfo), "/sys/block/%s/device", sysblkdevname); if (stat64(sysblkinfo, &statbuf)==0) { outdev->devtype=BLKDEV_PHYSDISK; snprintf(sysblkinfo, sizeof(sysblkinfo), "/sys/block/%s/device/model", sysblkdevname); if ( ((finfo=fopen(sysblkinfo, "rb")) != NULL) && (fread(temp, 1, sizeof(temp), finfo)>0) && fclose(finfo)==0 ) for (i=0; (temp[i]!=0) && (temp[i]!='\r') && (temp[i]!='\n'); i++) outdev->name[i]=temp[i]; } else { outdev->devtype=BLKDEV_FILESYSDEV; } // get blkid infos about the device (label, uuid) blkid_cache cache = NULL; if (blkid_get_cache(&cache, NULL) < 0) return -1; if ((dev=blkid_get_dev(cache, outdev->longname, BLKID_DEV_NORMAL))!=NULL) { iter = blkid_tag_iterate_begin(dev); while (blkid_tag_next(iter, &type, &value)==0) { if (strcmp(type, "LABEL")==0) snprintf(outdev->label, sizeof(outdev->label), "%s", value); else if (strcmp(type, "UUID")==0) snprintf(outdev->uuid, sizeof(outdev->uuid), "%s", value); else if (strcmp(type, "TYPE")==0) snprintf(outdev->fsname, sizeof(outdev->fsname), "%s", value); } blkid_tag_iterate_end(iter); // workaround: blkid < 1.41 don't know ext4 and say it is ext3 instead if (strcmp(outdev->fsname, "ext3")==0) { if (ext3_test(outdev->longname)==true) snprintf(outdev->fsname, sizeof(outdev->fsname), "ext3"); else // cannot run ext4_test(): it would fail on an ext4 when e2fsprogs < 1.41 snprintf(outdev->fsname, sizeof(outdev->fsname), "ext4"); } } blkid_put_cache(cache); // free memory allocated by blkid_get_cache return 0; }
/* * Pipe data from a list of files to standard output, giving information * about the transfer on standard error according to the given options. * * Returns nonzero on error. */ int pv_main_loop(pvstate_t state) { long written, lineswritten; long long total_written, since_last, cansend; long double target; int eof_in, eof_out, final_update; struct timeval start_time, next_update, next_ratecheck, cur_time; struct timeval init_time, next_remotecheck; long double elapsed; struct stat64 sb; int fd, n; /* * "written" is ALWAYS bytes written by the last transfer. * * "lineswritten" is the lines written by the last transfer, * but is only updated in line mode. * * "total_written" is the total bytes written since the start, * or in line mode, the total lines written since the start. * * "since_last" is the bytes written since the last display, * or in line mode, the lines written since the last display. * * The remaining variables are all unchanged by linemode. */ fd = -1; pv_crs_init(state); eof_in = 0; eof_out = 0; total_written = 0; since_last = 0; gettimeofday(&start_time, NULL); gettimeofday(&cur_time, NULL); next_update.tv_sec = start_time.tv_sec; next_update.tv_usec = start_time.tv_usec; pv_timeval_add_usec(&next_update, (long) (1000000.0 * state->interval)); next_ratecheck.tv_sec = start_time.tv_sec; next_ratecheck.tv_usec = start_time.tv_usec; next_remotecheck.tv_sec = start_time.tv_sec; next_remotecheck.tv_usec = start_time.tv_usec; target = 0; final_update = 0; n = 0; fd = pv_next_file(state, n, -1); if (fd < 0) { if (state->cursor) pv_crs_fini(state); return state->exit_status; } /* * Set target buffer size if the initial file's block size can be * read and we weren't given a target buffer size. */ if (0 == fstat64(fd, &sb)) { unsigned long long sz; sz = sb.st_blksize * 32; if (sz > BUFFER_SIZE_MAX) sz = BUFFER_SIZE_MAX; state->target_buffer_size = sz; } if (0 == state->target_buffer_size) state->target_buffer_size = BUFFER_SIZE; while ((!(eof_in && eof_out)) || (!final_update)) { cansend = 0; /* * Check for remote messages from -R every short while */ if ((cur_time.tv_sec > next_remotecheck.tv_sec) || (cur_time.tv_sec == next_remotecheck.tv_sec && cur_time.tv_usec >= next_remotecheck.tv_usec)) { pv_remote_check(state); pv_timeval_add_usec(&next_remotecheck, REMOTE_INTERVAL); } if (state->pv_sig_abort) break; if (state->rate_limit > 0) { gettimeofday(&cur_time, NULL); if ((cur_time.tv_sec > next_ratecheck.tv_sec) || (cur_time.tv_sec == next_ratecheck.tv_sec && cur_time.tv_usec >= next_ratecheck.tv_usec)) { target += ((long double) (state->rate_limit)) / (long double) (1000000 / RATE_GRANULARITY); pv_timeval_add_usec(&next_ratecheck, RATE_GRANULARITY); } cansend = target; } /* * If we have to stop at "size" bytes, make sure we don't * try to write more than we're allowed to. */ if ((0 < state->size) && (state->stop_at_size)) { if ((state->size < (total_written + cansend)) || ((0 == cansend) && (0 == state->rate_limit))) { cansend = state->size - total_written; if (0 >= cansend) { eof_in = 1; eof_out = 1; } } } if ((0 < state->size) && (state->stop_at_size) && (0 >= cansend) && eof_in && eof_out) { written = 0; } else { written = pv_transfer(state, fd, &eof_in, &eof_out, cansend, &lineswritten); } if (written < 0) { if (state->cursor) pv_crs_fini(state); return state->exit_status; } if (state->linemode) { since_last += lineswritten; total_written += lineswritten; if (state->rate_limit > 0) target -= lineswritten; } else { since_last += written; total_written += written; if (state->rate_limit > 0) target -= written; } if (eof_in && eof_out && n < (state->input_file_count - 1)) { n++; fd = pv_next_file(state, n, fd); if (fd < 0) { if (state->cursor) pv_crs_fini(state); return state->exit_status; } eof_in = 0; eof_out = 0; } gettimeofday(&cur_time, NULL); if (eof_in && eof_out) { final_update = 1; next_update.tv_sec = cur_time.tv_sec - 1; } if (state->no_op) continue; /* * If -W was given, we don't output anything until we have * written a byte (or line, in line mode), at which point * we then count time as if we started when the first byte * was received. */ if (state->wait) { if (state->linemode) { if (lineswritten < 1) continue; } else { if (written < 1) continue; } state->wait = 0; /* * Reset the timer offset counter now that data * transfer has begun, otherwise if we had been * stopped and started (with ^Z / SIGTSTOP) * previously (while waiting for data), the timers * will be wrongly offset. * * While we reset the offset counter we must disable * SIGTSTOP so things don't mess up. */ pv_sig_nopause(); gettimeofday(&start_time, NULL); state->pv_sig_toffset.tv_sec = 0; state->pv_sig_toffset.tv_usec = 0; pv_sig_allowpause(); next_update.tv_sec = start_time.tv_sec; next_update.tv_usec = start_time.tv_usec; pv_timeval_add_usec(&next_update, (long) (1000000.0 * state->interval)); } if ((cur_time.tv_sec < next_update.tv_sec) || (cur_time.tv_sec == next_update.tv_sec && cur_time.tv_usec < next_update.tv_usec)) { continue; } pv_timeval_add_usec(&next_update, (long) (1000000.0 * state->interval)); if (next_update.tv_sec < cur_time.tv_sec) { next_update.tv_sec = cur_time.tv_sec; next_update.tv_usec = cur_time.tv_usec; } else if (next_update.tv_sec == cur_time.tv_sec && next_update.tv_usec < cur_time.tv_usec) { next_update.tv_usec = cur_time.tv_usec; } init_time.tv_sec = start_time.tv_sec + state->pv_sig_toffset.tv_sec; init_time.tv_usec = start_time.tv_usec + state->pv_sig_toffset.tv_usec; if (init_time.tv_usec >= 1000000) { init_time.tv_sec++; init_time.tv_usec -= 1000000; } if (init_time.tv_usec < 0) { init_time.tv_sec--; init_time.tv_usec += 1000000; } elapsed = cur_time.tv_sec - init_time.tv_sec; elapsed += (cur_time.tv_usec - init_time.tv_usec) / 1000000.0; if (final_update) since_last = -1; if (state->pv_sig_newsize) { state->pv_sig_newsize = 0; pv_screensize(&(state->width), &(state->height)); } pv_display(state, elapsed, since_last, total_written); since_last = 0; } if (state->cursor) { pv_crs_fini(state); } else { if ((!state->numeric) && (!state->no_op)) write(STDERR_FILENO, "\n", 1); } if (state->pv_sig_abort) state->exit_status |= 32; return state->exit_status; }
int do_test (int argc, char *argv[]) { int fd; int fd2; int fd3; struct stat64 st; int val; int result = 0; /* Create the temporary file. */ fd = mkstemp (name); if (fd == -1) { printf ("cannot open temporary file: %m\n"); return 1; } if (fstat64 (fd, &st) != 0) { printf ("cannot stat test file: %m\n"); return 1; } if (! S_ISREG (st.st_mode) || st.st_size != 0) { puts ("file not created correctly"); return 1; } /* Get the flags with fcntl(). */ val = fcntl (fd, F_GETFL); if (val == -1) { printf ("fcntl(fd, F_GETFL) failed: %m\n"); result = 1; } else if ((val & O_ACCMODE) != O_RDWR) { puts ("temporary file not opened for read and write"); result = 1; } /* Set the flags to something else. */ if (fcntl (fd, F_SETFL, O_RDONLY) == -1) { printf ("fcntl(fd, F_SETFL, O_RDONLY) failed: %m\n"); result = 1; } val = fcntl (fd, F_GETFL); if (val == -1) { printf ("fcntl(fd, F_GETFL) after F_SETFL failed: %m\n"); result = 1; } else if ((val & O_ACCMODE) != O_RDWR) { puts ("temporary file access mode changed"); result = 1; } /* Set the flags to something else. */ if (fcntl (fd, F_SETFL, O_APPEND) == -1) { printf ("fcntl(fd, F_SETFL, O_APPEND) failed: %m\n"); result = 1; } val = fcntl (fd, F_GETFL); if (val == -1) { printf ("fcntl(fd, F_GETFL) after second F_SETFL failed: %m\n"); result = 1; } else if ((val & O_APPEND) == 0) { puts ("O_APPEND not set"); result = 1; } val = fcntl (fd, F_GETFD); if (val == -1) { printf ("fcntl(fd, F_GETFD) failed: %m\n"); result = 1; } else if (fcntl (fd, F_SETFD, val | FD_CLOEXEC) == -1) { printf ("fcntl(fd, F_SETFD, FD_CLOEXEC) failed: %m\n"); result = 1; } else { val = fcntl (fd, F_GETFD); if (val == -1) { printf ("fcntl(fd, F_GETFD) after F_SETFD failed: %m\n"); result = 1; } else if ((val & FD_CLOEXEC) == 0) { puts ("FD_CLOEXEC not set"); result = 1; } } /* Get a number of a free descriptor. If /dev/null is not available don't continue testing. */ fd2 = open (_PATH_DEVNULL, O_RDWR); if (fd2 == -1) return result; close (fd2); fd3 = fcntl (fd, F_DUPFD, fd2 + 1); if (fd3 == -1) { printf ("fcntl(fd, F_DUPFD, %d) failed: %m\n", fd2 + 1); result = 1; } else if (fd3 <= fd2) { printf ("F_DUPFD returned %d which is not larger than %d\n", fd3, fd2); result = 1; } if (fd3 != -1) { val = fcntl (fd3, F_GETFD); if (val == -1) { printf ("fcntl(fd3, F_GETFD) after F_DUPFD failed: %m\n"); result = 1; } else if ((val & FD_CLOEXEC) != 0) { puts ("FD_CLOEXEC still set"); result = 1; } close (fd3); } return result; }
file_error osd_open(const char *path, UINT32 openflags, osd_file **file, UINT64 *filesize) { UINT32 access; const char *src; char *dst; #if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_OS2) struct stat st; #else struct stat64 st; #endif char *tmpstr, *envstr; int i, j; file_error filerr = FILERR_NONE; tmpstr = NULL; // allocate a file object, plus space for the converted filename *file = (osd_file *) osd_malloc_array(sizeof(**file) + sizeof(char) * strlen(path)); if (*file == NULL) { filerr = FILERR_OUT_OF_MEMORY; goto error; } if (sdl_check_socket_path(path)) { (*file)->type = SDLFILE_SOCKET; filerr = sdl_open_socket(path, openflags, file, filesize); goto error; } if (strlen(sdlfile_ptty_identifier) > 0 && strncmp(path, sdlfile_ptty_identifier, strlen(sdlfile_ptty_identifier)) == 0) { (*file)->type = SDLFILE_PTTY; filerr = sdl_open_ptty(path, openflags, file, filesize); goto error; } (*file)->type = SDLFILE_FILE; // convert the path into something compatible dst = (*file)->filename; for (src = path; *src != 0; src++) *dst++ = (*src == INVPATHSEPCH) ? PATHSEPCH : *src; *dst++ = 0; // select the file open modes if (openflags & OPEN_FLAG_WRITE) { access = (openflags & OPEN_FLAG_READ) ? O_RDWR : O_WRONLY; access |= (openflags & OPEN_FLAG_CREATE) ? (O_CREAT | O_TRUNC) : 0; } else if (openflags & OPEN_FLAG_READ) { access = O_RDONLY; } else { filerr = FILERR_INVALID_ACCESS; goto error; } tmpstr = (char *) osd_malloc_array(strlen((*file)->filename)+1); strcpy(tmpstr, (*file)->filename); // does path start with an environment variable? if (tmpstr[0] == '$') { char *envval; envstr = (char *) osd_malloc_array(strlen(tmpstr)+1); strcpy(envstr, tmpstr); i = 0; while (envstr[i] != PATHSEPCH && envstr[i] != 0 && envstr[i] != '.') { i++; } envstr[i] = '\0'; envval = osd_getenv(&envstr[1]); if (envval != NULL) { j = strlen(envval) + strlen(tmpstr) + 1; osd_free(tmpstr); tmpstr = (char *) osd_malloc_array(j); // start with the value of $HOME strcpy(tmpstr, envval); // replace the null with a path separator again envstr[i] = PATHSEPCH; // append it strcat(tmpstr, &envstr[i]); } else fprintf(stderr, "Warning: osd_open environment variable %s not found.\n", envstr); osd_free(envstr); } #if defined(SDLMAME_WIN32) || defined(SDLMAME_OS2) access |= O_BINARY; #endif // attempt to open the file #if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_OS2) (*file)->handle = open(tmpstr, access, 0666); #else (*file)->handle = open64(tmpstr, access, 0666); #endif if ((*file)->handle == -1) { // create the path if necessary if ((openflags & OPEN_FLAG_CREATE) && (openflags & OPEN_FLAG_CREATE_PATHS)) { char *pathsep = strrchr(tmpstr, PATHSEPCH); if (pathsep != NULL) { int error; // create the path up to the file *pathsep = 0; error = create_path_recursive(tmpstr); *pathsep = PATHSEPCH; // attempt to reopen the file if (error == NO_ERROR) { #if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_OS2) (*file)->handle = open(tmpstr, access, 0666); #else (*file)->handle = open64(tmpstr, access, 0666); #endif } } } // if we still failed, clean up and osd_free if ((*file)->handle == -1) { osd_free(*file); *file = NULL; osd_free(tmpstr); return error_to_file_error(errno); } } // get the file size #if defined(SDLMAME_DARWIN) || defined(SDLMAME_WIN32) || defined(SDLMAME_NO64BITIO) || defined(SDLMAME_BSD) || defined(SDLMAME_OS2) fstat((*file)->handle, &st); #else fstat64((*file)->handle, &st); #endif *filesize = (UINT64)st.st_size; error: // cleanup if (filerr != FILERR_NONE && *file != NULL) { osd_free(*file); *file = NULL; } if (tmpstr) osd_free(tmpstr); return filerr; }
/* Try to get a file descriptor for the shared meory segment containing the database. */ static struct mapped_database * get_mapping (request_type type, const char *key, struct mapped_database **mappedp) { struct mapped_database *result = NO_MAPPING; #ifdef SCM_RIGHTS const size_t keylen = strlen (key) + 1; char resdata[keylen]; int saved_errno = errno; int mapfd = -1; /* Send the request. */ struct iovec iov[2]; request_header req; int sock = open_socket (); if (sock < 0) goto out; req.version = NSCD_VERSION; req.type = type; req.key_len = keylen; iov[0].iov_base = &req; iov[0].iov_len = sizeof (req); iov[1].iov_base = (void *) key; iov[1].iov_len = keylen; if (__builtin_expect (TEMP_FAILURE_RETRY (__writev (sock, iov, 2)) != iov[0].iov_len + iov[1].iov_len, 0)) /* We cannot even write the request. */ goto out_close2; /* Room for the data sent along with the file descriptor. We expect the key name back. */ iov[0].iov_base = resdata; iov[0].iov_len = keylen; union { struct cmsghdr hdr; char bytes[CMSG_SPACE (sizeof (int))]; } buf; struct msghdr msg = { .msg_iov = iov, .msg_iovlen = 1, .msg_control = buf.bytes, .msg_controllen = sizeof (buf) }; struct cmsghdr *cmsg = CMSG_FIRSTHDR (&msg); cmsg->cmsg_level = SOL_SOCKET; cmsg->cmsg_type = SCM_RIGHTS; cmsg->cmsg_len = CMSG_LEN (sizeof (int)); /* This access is well-aligned since BUF is correctly aligned for an int and CMSG_DATA preserves this alignment. */ *(int *) CMSG_DATA (cmsg) = -1; msg.msg_controllen = cmsg->cmsg_len; if (wait_on_socket (sock) <= 0) goto out_close2; # ifndef MSG_NOSIGNAL # define MSG_NOSIGNAL 0 # endif if (__builtin_expect (TEMP_FAILURE_RETRY (__recvmsg (sock, &msg, MSG_NOSIGNAL)) != keylen, 0)) goto out_close2; mapfd = *(int *) CMSG_DATA (cmsg); if (__builtin_expect (CMSG_FIRSTHDR (&msg)->cmsg_len != CMSG_LEN (sizeof (int)), 0)) goto out_close; struct stat64 st; if (__builtin_expect (strcmp (resdata, key) != 0, 0) || __builtin_expect (fstat64 (mapfd, &st) != 0, 0) || __builtin_expect (st.st_size < sizeof (struct database_pers_head), 0)) goto out_close; struct database_pers_head head; if (__builtin_expect (TEMP_FAILURE_RETRY (__pread (mapfd, &head, sizeof (head), 0)) != sizeof (head), 0)) goto out_close; if (__builtin_expect (head.version != DB_VERSION, 0) || __builtin_expect (head.header_size != sizeof (head), 0) /* This really should not happen but who knows, maybe the update thread got stuck. */ || __builtin_expect (! head.nscd_certainly_running && head.timestamp + MAPPING_TIMEOUT < time (NULL), 0)) goto out_close; size_t size = (sizeof (head) + roundup (head.module * sizeof (ref_t), ALIGN) + head.data_size); if (__builtin_expect (st.st_size < size, 0)) goto out_close; /* The file is large enough, map it now. */ void *mapping = __mmap (NULL, size, PROT_READ, MAP_SHARED, mapfd, 0); if (__builtin_expect (mapping != MAP_FAILED, 1)) { /* Allocate a record for the mapping. */ struct mapped_database *newp = malloc (sizeof (*newp)); if (newp == NULL) { /* Ugh, after all we went through the memory allocation failed. */ __munmap (mapping, size); goto out_close; } newp->head = mapping; newp->data = ((char *) mapping + head.header_size + roundup (head.module * sizeof (ref_t), ALIGN)); newp->mapsize = size; /* Set counter to 1 to show it is usable. */ newp->counter = 1; result = newp; } out_close: __close (mapfd); out_close2: __close (sock); out: __set_errno (saved_errno); #endif /* SCM_RIGHTS */ struct mapped_database *oldval = *mappedp; *mappedp = result; if (oldval != NULL && atomic_decrement_val (&oldval->counter) == 0) __nscd_unmap (oldval); return result; } struct mapped_database * __nscd_get_map_ref (request_type type, const char *name, struct locked_map_ptr *mapptr, int *gc_cyclep) { struct mapped_database *cur = mapptr->mapped; if (cur == NO_MAPPING) return cur; int cnt = 0; while (atomic_compare_and_exchange_val_acq (&mapptr->lock, 1, 0) != 0) { // XXX Best number of rounds? if (++cnt > 5) return NO_MAPPING; atomic_delay (); } cur = mapptr->mapped; if (__builtin_expect (cur != NO_MAPPING, 1)) { /* If not mapped or timestamp not updated, request new map. */ if (cur == NULL || (cur->head->nscd_certainly_running == 0 && cur->head->timestamp + MAPPING_TIMEOUT < time (NULL))) cur = get_mapping (type, name, &mapptr->mapped); if (__builtin_expect (cur != NO_MAPPING, 1)) { if (__builtin_expect (((*gc_cyclep = cur->head->gc_cycle) & 1) != 0, 0)) cur = NO_MAPPING; else atomic_increment (&cur->counter); } } mapptr->lock = 0; return cur; } const struct datahead * __nscd_cache_search (request_type type, const char *key, size_t keylen, const struct mapped_database *mapped) { unsigned long int hash = __nis_hash (key, keylen) % mapped->head->module; ref_t work = mapped->head->array[hash]; while (work != ENDREF) { struct hashentry *here = (struct hashentry *) (mapped->data + work); if (type == here->type && keylen == here->len && memcmp (key, mapped->data + here->key, keylen) == 0) { /* We found the entry. Increment the appropriate counter. */ const struct datahead *dh = (struct datahead *) (mapped->data + here->packet); /* See whether we must ignore the entry or whether something is wrong because garbage collection is in progress. */ if (dh->usable && ((char *) dh + dh->allocsize <= (char *) mapped->head + mapped->mapsize)) return dh; } work = here->next; } return NULL; }
dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat) #endif { char fname[MAXPATHLEN]; struct stat64 st; int fd, err, bits; dt_module_t *dmp; const char *s; size_t shstrs; GElf_Shdr sh; Elf_Data *dp; Elf_Scn *sp; #if defined(sun) (void) snprintf(fname, sizeof (fname), "%s/%s/object", OBJFS_ROOT, name); #else GElf_Ehdr ehdr; GElf_Phdr ph; char name[MAXPATHLEN]; uintptr_t mapbase, alignmask; int i = 0; int is_elf_obj; (void) strlcpy(name, k_stat->name, sizeof(name)); (void) strlcpy(fname, k_stat->pathname, sizeof(fname)); #endif if ((fd = open(fname, O_RDONLY)) == -1 || fstat64(fd, &st) == -1 || (dmp = dt_module_create(dtp, name)) == NULL) { dt_dprintf("failed to open %s: %s\n", fname, strerror(errno)); (void) close(fd); return; } /* * Since the module can unload out from under us (and /system/object * will return ENOENT), tell libelf to cook the entire file now and * then close the underlying file descriptor immediately. If this * succeeds, we know that we can continue safely using dmp->dm_elf. */ dmp->dm_elf = elf_begin(fd, ELF_C_READ, NULL); err = elf_cntl(dmp->dm_elf, ELF_C_FDREAD); (void) close(fd); if (dmp->dm_elf == NULL || err == -1 || elf_getshdrstrndx(dmp->dm_elf, &shstrs) == -1) { dt_dprintf("failed to load %s: %s\n", fname, elf_errmsg(elf_errno())); dt_module_destroy(dtp, dmp); return; } switch (gelf_getclass(dmp->dm_elf)) { case ELFCLASS32: dmp->dm_ops = &dt_modops_32; bits = 32; break; case ELFCLASS64: dmp->dm_ops = &dt_modops_64; bits = 64; break; default: dt_dprintf("failed to load %s: unknown ELF class\n", fname); dt_module_destroy(dtp, dmp); return; } #if defined(__FreeBSD__) mapbase = (uintptr_t)k_stat->address; gelf_getehdr(dmp->dm_elf, &ehdr); is_elf_obj = (ehdr.e_type == ET_REL); if (is_elf_obj) { dmp->dm_sec_offsets = malloc(ehdr.e_shnum * sizeof(*dmp->dm_sec_offsets)); if (dmp->dm_sec_offsets == NULL) { dt_dprintf("failed to allocate memory\n"); dt_module_destroy(dtp, dmp); return; } } #endif /* * Iterate over the section headers locating various sections of * interest and use their attributes to flesh out the dt_module_t. */ for (sp = NULL; (sp = elf_nextscn(dmp->dm_elf, sp)) != NULL; ) { if (gelf_getshdr(sp, &sh) == NULL || sh.sh_type == SHT_NULL || (s = elf_strptr(dmp->dm_elf, shstrs, sh.sh_name)) == NULL) continue; /* skip any malformed sections */ #if defined(__FreeBSD__) if (sh.sh_size == 0) continue; if (is_elf_obj && (sh.sh_type == SHT_PROGBITS || sh.sh_type == SHT_NOBITS)) { alignmask = sh.sh_addralign - 1; mapbase += alignmask; mapbase &= ~alignmask; sh.sh_addr = mapbase; dmp->dm_sec_offsets[elf_ndxscn(sp)] = sh.sh_addr; mapbase += sh.sh_size; } #endif if (strcmp(s, ".text") == 0) { dmp->dm_text_size = sh.sh_size; dmp->dm_text_va = sh.sh_addr; } else if (strcmp(s, ".data") == 0) { dmp->dm_data_size = sh.sh_size; dmp->dm_data_va = sh.sh_addr; } else if (strcmp(s, ".bss") == 0) { dmp->dm_bss_size = sh.sh_size; dmp->dm_bss_va = sh.sh_addr; } else if (strcmp(s, ".info") == 0 && (dp = elf_getdata(sp, NULL)) != NULL) { bcopy(dp->d_buf, &dmp->dm_info, MIN(sh.sh_size, sizeof (dmp->dm_info))); } else if (strcmp(s, ".filename") == 0 && (dp = elf_getdata(sp, NULL)) != NULL) { (void) strlcpy(dmp->dm_file, dp->d_buf, sizeof (dmp->dm_file)); } } dmp->dm_flags |= DT_DM_KERNEL; #if defined(sun) dmp->dm_modid = (int)OBJFS_MODID(st.st_ino); #else /* * Include .rodata and special sections into .text. * This depends on default section layout produced by GNU ld * for ELF objects and libraries: * [Text][R/O data][R/W data][Dynamic][BSS][Non loadable] */ dmp->dm_text_size = dmp->dm_data_va - dmp->dm_text_va; #if defined(__i386__) /* * Find the first load section and figure out the relocation * offset for the symbols. The kernel module will not need * relocation, but the kernel linker modules will. */ for (i = 0; gelf_getphdr(dmp->dm_elf, i, &ph) != NULL; i++) { if (ph.p_type == PT_LOAD) { dmp->dm_reloc_offset = k_stat->address - ph.p_vaddr; break; } } #endif #endif if (dmp->dm_info.objfs_info_primary) dmp->dm_flags |= DT_DM_PRIMARY; dt_dprintf("opened %d-bit module %s (%s) [%d]\n", bits, dmp->dm_name, dmp->dm_file, dmp->dm_modid); }
static int do_test (void) { /* fdopendir takes over the descriptor, make a copy. */ int dupfd = dup (dir_fd); if (dupfd == -1) { puts ("dup failed"); return 1; } if (lseek (dupfd, 0, SEEK_SET) != 0) { puts ("1st lseek failed"); return 1; } /* The directory should be empty safe the . and .. files. */ DIR *dir = fdopendir (dupfd); if (dir == NULL) { puts ("fdopendir failed"); return 1; } struct dirent64 *d; while ((d = readdir64 (dir)) != NULL) if (strcmp (d->d_name, ".") != 0 && strcmp (d->d_name, "..") != 0) { printf ("temp directory contains file \"%s\"\n", d->d_name); return 1; } closedir (dir); /* Try to create a file. */ int fd = openat (dir_fd, "some-file", O_CREAT|O_RDWR|O_EXCL, 0666); if (fd == -1) { if (errno == ENOSYS) { puts ("*at functions not supported"); return 0; } puts ("file creation failed"); return 1; } write (fd, "hello", 5); puts ("file created"); struct stat64 st1; if (fstat64 (fd, &st1) != 0) { puts ("fstat64 failed"); return 1; } /* Before closing the file, try using this file descriptor to open another file. This must fail. */ if (fchownat (fd, "some-file", 1, 1, 0) != -1) { puts ("fchownat using descriptor for normal file worked"); return 1; } if (errno != ENOTDIR) { puts ("\ error for fchownat using descriptor for normal file not ENOTDIR "); return 1; }
static int find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name, const char *debuglink_file, GElf_Word debuglink_crc, char **debuginfo_file_name) { bool cancheck = debuglink_crc != (GElf_Word) 0; const char *file_basename = file_name == NULL ? NULL : basename (file_name); char *localname = NULL; if (debuglink_file == NULL) { /* For a alt debug multi file we need a name, for a separate debug name we may be able to fall back on file_basename.debug. */ if (file_basename == NULL || mod->dw != NULL) { errno = 0; return -1; } size_t len = strlen (file_basename); localname = malloc (len + sizeof ".debug"); if (unlikely (localname == NULL)) return -1; memcpy (localname, file_basename, len); memcpy (&localname[len], ".debug", sizeof ".debug"); debuglink_file = localname; cancheck = false; } /* Look for a file named DEBUGLINK_FILE in the directories indicated by the debug directory path setting. */ const Dwfl_Callbacks *const cb = mod->dwfl->callbacks; char *localpath = strdup ((cb->debuginfo_path ? *cb->debuginfo_path : NULL) ?: DEFAULT_DEBUGINFO_PATH); if (unlikely (localpath == NULL)) { free (localname); return -1; } /* A leading - or + in the whole path sets whether to check file CRCs. */ bool defcheck = true; char *path = localpath; if (path[0] == '-' || path[0] == '+') { defcheck = path[0] == '+'; ++path; } /* XXX dev/ino should be cached in struct dwfl_file. */ struct stat64 main_stat; if (unlikely ((mod->main.fd != -1 ? fstat64 (mod->main.fd, &main_stat) : file_name != NULL ? stat64 (file_name, &main_stat) : -1) < 0)) { main_stat.st_dev = 0; main_stat.st_ino = 0; } char *file_dirname = (file_basename == file_name ? NULL : strndup (file_name, file_basename - 1 - file_name)); if (file_basename != file_name && file_dirname == NULL) { free (localpath); free (localname); return -1; } char *p; while ((p = strsep (&path, ":")) != NULL) { /* A leading - or + says whether to check file CRCs for this element. */ bool check = defcheck; if (*p == '+' || *p == '-') check = *p++ == '+'; check = check && cancheck; const char *dir, *subdir, *file; switch (p[0]) { case '\0': /* An empty entry says to try the main file's directory. */ dir = file_dirname; subdir = NULL; file = debuglink_file; break; case '/': /* An absolute path says to look there for a subdirectory named by the main file's absolute directory. This cannot be applied to a relative file name. For alt debug files it means to look for the basename file in that dir or the .dwz subdir (see below). */ if (mod->dw == NULL && (file_dirname == NULL || file_dirname[0] != '/')) continue; dir = p; if (mod->dw == NULL) { subdir = file_dirname; /* We want to explore all sub-subdirs. Chop off one slash at a time. */ explore_dir: subdir = strchr (subdir, '/'); if (subdir != NULL) subdir = subdir + 1; if (subdir && *subdir == 0) continue; file = debuglink_file; } else { subdir = NULL; file = basename (debuglink_file); } break; default: /* A relative path says to try a subdirectory of that name in the main file's directory. */ dir = file_dirname; subdir = p; file = debuglink_file; break; } char *fname = NULL; int fd = try_open (&main_stat, dir, subdir, file, &fname); if (fd < 0) switch (errno) { case ENOENT: case ENOTDIR: /* If we are looking for the alt file also try the .dwz subdir. But only if this is the empty or absolute path. */ if (mod->dw != NULL && (p[0] == '\0' || p[0] == '/')) { fd = try_open (&main_stat, dir, ".dwz", basename (file), &fname); if (fd < 0) { if (errno != ENOENT && errno != ENOTDIR) goto fail_free; else continue; } break; } /* If possible try again with a sub-subdir. */ if (mod->dw == NULL && subdir) goto explore_dir; continue; default: goto fail_free; } if (validate (mod, fd, check, debuglink_crc)) { free (localpath); free (localname); free (file_dirname); *debuginfo_file_name = fname; return fd; } free (fname); close (fd); } /* No dice. */ errno = 0; fail_free: free (localpath); free (localname); free (file_dirname); return -1; }
/* * Returns the number of bytes in a partition */ blkid_loff_t blkid_get_dev_size(int fd) { int valid_blkgetsize64 = 1; #ifdef __linux__ struct utsname ut; #endif unsigned long long size64; unsigned long size; blkid_loff_t high, low; #ifdef FDGETPRM struct floppy_struct this_floppy; #endif #ifdef HAVE_SYS_DISKLABEL_H int part = -1; struct disklabel lab; struct partition *pp; char ch; struct stat st; #endif /* HAVE_SYS_DISKLABEL_H */ #ifdef DKIOCGETBLOCKCOUNT /* For Apple Darwin */ if (ioctl(fd, DKIOCGETBLOCKCOUNT, &size64) >= 0) { if ((sizeof(blkid_loff_t) < sizeof(unsigned long long)) && (size64 << 9 > 0xFFFFFFFF)) return 0; /* EFBIG */ return (blkid_loff_t) size64 << 9; } #endif #ifdef BLKGETSIZE64 #ifdef __linux__ if ((uname(&ut) == 0) && ((ut.release[0] == '2') && (ut.release[1] == '.') && (ut.release[2] < '6') && (ut.release[3] == '.'))) valid_blkgetsize64 = 0; #endif if (valid_blkgetsize64 && ioctl(fd, BLKGETSIZE64, &size64) >= 0) { if ((sizeof(blkid_loff_t) < sizeof(unsigned long long)) && ((size64) > 0xFFFFFFFF)) return 0; /* EFBIG */ return size64; } #endif #ifdef BLKGETSIZE if (ioctl(fd, BLKGETSIZE, &size) >= 0) return (blkid_loff_t)size << 9; #endif /* tested on FreeBSD 6.1-RELEASE i386 */ #ifdef DIOCGMEDIASIZE if (ioctl(fd, DIOCGMEDIASIZE, &size64) >= 0) return (off_t)size64; #endif /* DIOCGMEDIASIZE */ #ifdef FDGETPRM if (ioctl(fd, FDGETPRM, &this_floppy) >= 0) return (blkid_loff_t)this_floppy.size << 9; #endif #ifdef HAVE_SYS_DISKLABEL_H /* * This code works for FreeBSD 4.11 i386, except for the full device * (such as /dev/ad0). It doesn't work properly for newer FreeBSD * though. FreeBSD >= 5.0 should be covered by the DIOCGMEDIASIZE * above however. * * Note that FreeBSD >= 4.0 has disk devices as unbuffered (raw, * character) devices, so we need to check for S_ISCHR, too. */ if ((fstat(fd, &st) >= 0) && (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))) part = st.st_rdev & 7; if (part >= 0 && (ioctl(fd, DIOCGDINFO, (char *)&lab) >= 0)) { pp = &lab.d_partitions[part]; if (pp->p_size) return pp->p_size << 9; } #endif /* HAVE_SYS_DISKLABEL_H */ { #ifdef HAVE_FSTAT64 struct stat64 st; if (fstat64(fd, &st) == 0) #else struct stat st; if (fstat(fd, &st) == 0) #endif if (S_ISREG(st.st_mode)) return st.st_size; } /* * OK, we couldn't figure it out by using a specialized ioctl, * which is generally the best way. So do binary search to * find the size of the partition. */ low = 0; for (high = 1024; valid_offset(fd, high); high *= 2) low = high; while (low < high - 1) { const blkid_loff_t mid = (low + high) / 2; if (valid_offset(fd, mid)) low = mid; else high = mid; } return low + 1; }
int charmap_conversion (const char *from_code, struct charmap_t *from_charmap, const char *to_code, struct charmap_t *to_charmap, int argc, int remaining, char *argv[], const char *output_file) { struct convtable *cvtbl; int status = EXIT_SUCCESS; /* We have three different cases to handle: - both, from_charmap and to_charmap, are available. This means we can assume that the symbolic names match and use them to create the mapping. - only from_charmap is available. In this case we can only hope that the symbolic names used are of the <Uxxxx> form in which case we can use a UCS4->"to_code" iconv() conversion for the second step. - only to_charmap is available. This is similar, only that we would use iconv() for the "to_code"->UCS4 conversion. We first create a table which maps input bytes into output bytes. Once this is done we can handle all three of the cases above equally. */ if (from_charmap != NULL) { if (to_charmap == NULL) cvtbl = use_from_charmap (from_charmap, to_code); else cvtbl = use_both_charmaps (from_charmap, to_charmap); } else { assert (to_charmap != NULL); cvtbl = use_to_charmap (from_code, to_charmap); } /* If we couldn't generate a table stop now. */ if (cvtbl == NULL) return EXIT_FAILURE; /* Determine output file. */ FILE *output; if (output_file != NULL && strcmp (output_file, "-") != 0) { output = fopen (output_file, "w"); if (output == NULL) error (EXIT_FAILURE, errno, _("cannot open output file")); } else output = stdout; /* We can now start the conversion. */ if (remaining == argc) { if (process_file (cvtbl, stdin, output) != 0) status = EXIT_FAILURE; } else do { int fd; if (verbose) printf ("%s:\n", argv[remaining]); if (strcmp (argv[remaining], "-") == 0) fd = 0; else { fd = open (argv[remaining], O_RDONLY); if (fd == -1) { error (0, errno, _("cannot open input file `%s'"), argv[remaining]); status = EXIT_FAILURE; continue; } } #ifdef _POSIX_MAPPED_FILES struct stat64 st; char *addr; /* We have possibilities for reading the input file. First try to mmap() it since this will provide the fastest solution. */ if (fstat64 (fd, &st) == 0 && ((addr = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) != MAP_FAILED)) { /* Yes, we can use mmap(). The descriptor is not needed anymore. */ if (close (fd) != 0) error (EXIT_FAILURE, errno, _("error while closing input `%s'"), argv[remaining]); if (process_block (cvtbl, addr, st.st_size, output) < 0) { /* Something went wrong. */ status = EXIT_FAILURE; /* We don't need the input data anymore. */ munmap ((void *) addr, st.st_size); /* We cannot go on with producing output since it might lead to problem because the last output might leave the output stream in an undefined state. */ break; } /* We don't need the input data anymore. */ munmap ((void *) addr, st.st_size); } else #endif /* _POSIX_MAPPED_FILES */ { /* Read the file in pieces. */ if (process_fd (cvtbl, fd, output) != 0) { /* Something went wrong. */ status = EXIT_FAILURE; /* We don't need the input file anymore. */ close (fd); /* We cannot go on with producing output since it might lead to problem because the last output might leave the output stream in an undefined state. */ break; } /* Now close the file. */ close (fd); } } while (++remaining < argc); /* All done. */ return status; }