/* to track processes. */ int start_activity( int (details)(samrthread_t *, char **), int (destroy)(samrthread_t *), activitytype_t type, argbuf_t *args, char **jobidp) { samrthread_t *samtp; char jobstr[BUFFSIZ]; /* set up the pthread attributes to be used hereafter */ pthread_once(&samr_once_control, samr_once); /* Create samrthread_t structure */ samtp = mallocer(sizeof (samrthread_t)); if (samtp == NULL) return (-1); /* Initialize */ samtp->start = time(NULL); /* Start time */ samtp->pid = 0; samtp->tid = 0; samtp->type = type; /* specified by caller */ samtp->details = details; samtp->destroy = destroy; samtp->args = args; samtp->next = NULL; samtp->prev = NULL; /* Link structure into active list */ pthread_mutex_lock(samrlock); /* ++ LOCK */ samrjobnum++; /* ++ Allocate a jobid */ snprintf(jobstr, BUFFSIZ, "%d", samrjobnum); /* ++ */ samtp->jobid = copystr(jobstr); /* Keep copy of ascii string */ /* * copy the jobid prior to insertion into list so if copy fails * it is easier to cleanup */ *jobidp = copystr(jobstr); if (samtp->jobid == NULL || *jobidp == NULL) { if (*jobidp) { free(*jobidp); *jobidp = NULL; } if (samtp->jobid) { free(samtp->jobid); } free(samtp); /* caller is responsible for freeing any malloced args */ pthread_mutex_unlock(samrlock); /* ++ UNLOCK */ return (-1); } if (samrtlist == NULL) { samrtlist = samtp; } else { /* Insert structure into list */ samtp->next = samrtlist; samrtlist->prev = samtp; samrtlist = samtp; } pthread_mutex_unlock(samrlock); /* ++ UNLOCK */ return (0); }
/* * Shell interpreter image activator. A interpreter name beginning * at imgp->args->begin_argv is the minimal successful exit requirement. */ int exec_shell_imgact(struct image_params *imgp) { const char *image_header = imgp->image_header; const char *ihp; size_t length, offset; int error; /* a shell script? */ if (((const short *) image_header)[0] != SHELLMAGIC) return(-1); /* * Don't allow a shell script to be the shell for a shell * script. :-) */ if (imgp->interpreted) return(ENOEXEC); imgp->interpreted = 1; /* * Figure out the number of bytes that need to be reserved in the * argument string to copy the contents of the interpreter's command * line into the argument string. */ ihp = &image_header[2]; offset = 0; while (ihp < &image_header[PAGE_SIZE]) { /* Skip any whitespace */ if (*ihp == ' ' || *ihp == '\t') { ++ihp; continue; } /* End of line? */ if (*ihp == '\n' || *ihp == '#' || *ihp == '\0') break; /* Found a token */ do { ++offset; ++ihp; } while (ihp < &image_header[PAGE_SIZE] && *ihp != ' ' && *ihp != '\t' && *ihp != '\n' && *ihp != '#' && *ihp != '\0'); /* Take into account the \0 that will terminate the token */ ++offset; } /* If the script gives a null line as the interpreter, we bail */ if (offset == 0) return (ENOEXEC); /* It should not be possible for offset to exceed PAGE_SIZE */ KKASSERT(offset <= PAGE_SIZE); /* Check that we aren't too big */ if (ihp == &image_header[PAGE_SIZE]) return (ENAMETOOLONG); /* * The full path name of the original script file must be tagged * onto the end, adjust the offset to deal with it. * * The original argv0 is being replaced, set 'length' to the number * of bytes being removed. So 'offset' is the number of bytes being * added and 'length' is the number of bytes being removed. */ offset += strlen(imgp->args->fname) + 1; /* add fname */ length = strlen(imgp->args->begin_argv) + 1; /* bytes to delete */ if (offset - length > imgp->args->space) return (E2BIG); bcopy(imgp->args->begin_argv + length, imgp->args->begin_argv + offset, imgp->args->endp - (imgp->args->begin_argv + length)); offset -= length; /* calculate actual adjustment */ imgp->args->begin_envv += offset; imgp->args->endp += offset; imgp->args->space -= offset; /* decr argc remove old argv[0], incr argc for fname add, net 0 */ /* * Loop through the interpreter name yet again, copying as * we go. */ ihp = &image_header[2]; offset = 0; while (ihp < &image_header[PAGE_SIZE]) { /* Skip whitespace */ if (*ihp == ' ' || *ihp == '\t') { ++ihp; continue; } /* End of line? */ if (*ihp == '\n' || *ihp == '#' || *ihp == '\0') break; /* Found a token, copy it */ do { imgp->args->begin_argv[offset] = *ihp; ++ihp; ++offset; } while (ihp < &image_header[PAGE_SIZE] && *ihp != ' ' && *ihp != '\t' && *ihp != '\n' && *ihp != '#' && *ihp != '\0'); /* And terminate the argument */ imgp->args->begin_argv[offset] = '\0'; imgp->args->argc++; ++offset; } /* * Finally, add the filename onto the end for the interpreter to * use and copy the interpreter's name to imgp->interpreter_name * for exec to use. */ error = copystr(imgp->args->fname, imgp->args->buf + offset, imgp->args->space, &length); if (error == 0) { error = copystr(imgp->args->begin_argv, imgp->interpreter_name, MAXSHELLCMDLEN, &length); } return (error); }
int list_dir( ctx_t *c, int maxentries, char *filepath, char *restrictions, sqm_lst_t **direntries) /* ARGSUSED */ { int rval = 0; DIR *curdir; /* Variable for directory system calls */ struct dirent64 *entry; /* Pointer to a directory entry */ struct dirent64 *entryp; struct stat64 sout; restrict_t filter = {0}; char *data; /* Pointer to data item to add to list */ char fullpath[MAXPATHLEN]; /* Set up wildcard restrictions */ rval = set_restrict(restrictions, &filter); if (rval) { return (rval); } curdir = opendir(filepath); /* Set up to ask for directory entries */ if (curdir == NULL) { return (samrerr(SE_NOSUCHPATH, filepath)); } *direntries = lst_create(); /* Return results in this list */ if (*direntries == NULL) { closedir(curdir); return (-1); /* If allocation failed, samerr is set */ } entry = mallocer(sizeof (struct dirent64) + MAXPATHLEN + 1); if (entry == NULL) { closedir(curdir); lst_free(*direntries); *direntries = NULL; return (-1); } /* Walk through directory entries */ while ((rval = readdir64_r(curdir, entry, &entryp)) == 0) { if (entryp == NULL) { break; } if ((strcmp(entry->d_name, ".") == 0) || (strcmp(entry->d_name, "..") == 0)) { continue; } /* Create full pathname and get stat info */ snprintf( fullpath, MAXPATHLEN, "%s/%s", filepath, entry->d_name); if (stat64(fullpath, &sout) != 0) { continue; /* Ignore file which can't be stat'ed */ } if (check_restrict_stat(entry->d_name, &sout, &filter)) continue; /* Not this entry */ data = copystr(entry->d_name); /* Copy data to allocated mem */ if (data == NULL) { rval = -1; break; /* samerr already set */ } lst_append(*direntries, data); if ((*direntries)->length >= maxentries) break; /* Keep list to designated limits */ } free(entry); if (rval) { lst_free_deep(*direntries); /* On failure, don't return list */ *direntries = NULL; } else { lst_qsort(*direntries, node_cmp); } closedir(curdir); return (rval); }
/* * Starting at current directory, translate pathname pnp to end. * Leave pathname of final component in pnp, return the vnode * for the final component in *compvpp, and return the vnode * for the parent of the final component in dirvpp. * * This is the central routine in pathname translation and handles * multiple components in pathnames, separating them at /'s. It also * implements mounted file systems and processes symbolic links. * * vp is the vnode where the directory search should start. * * Reference counts: vp must be held prior to calling this function. rootvp * should only be held if rootvp != rootdir. */ int lookuppnvp( struct pathname *pnp, /* pathname to lookup */ struct pathname *rpnp, /* if non-NULL, return resolved path */ int flags, /* follow symlinks */ vnode_t **dirvpp, /* ptr for parent vnode */ vnode_t **compvpp, /* ptr for entry vnode */ vnode_t *rootvp, /* rootvp */ vnode_t *vp, /* directory to start search at */ cred_t *cr) /* user's credential */ { vnode_t *cvp; /* current component vp */ char component[MAXNAMELEN]; /* buffer for component (incl null) */ int error; int nlink; int lookup_flags; struct pathname presrvd; /* case preserved name */ struct pathname *pp = NULL; vnode_t *startvp; vnode_t *zonevp = curproc->p_zone->zone_rootvp; /* zone root */ int must_be_directory = 0; boolean_t retry_with_kcred; uint32_t auditing = AU_AUDITING(); CPU_STATS_ADDQ(CPU, sys, namei, 1); nlink = 0; cvp = NULL; if (rpnp) rpnp->pn_pathlen = 0; lookup_flags = dirvpp ? LOOKUP_DIR : 0; if (flags & FIGNORECASE) { lookup_flags |= FIGNORECASE; pn_alloc(&presrvd); pp = &presrvd; } if (auditing) audit_anchorpath(pnp, vp == rootvp); /* * Eliminate any trailing slashes in the pathname. * If there are any, we must follow all symlinks. * Also, we must guarantee that the last component is a directory. */ if (pn_fixslash(pnp)) { flags |= FOLLOW; must_be_directory = 1; } startvp = vp; next: retry_with_kcred = B_FALSE; /* * Make sure we have a directory. */ if (vp->v_type != VDIR) { error = ENOTDIR; goto bad; } if (rpnp && VN_CMP(vp, rootvp)) (void) pn_set(rpnp, "/"); /* * Process the next component of the pathname. */ if (error = pn_getcomponent(pnp, component)) { goto bad; } /* * Handle "..": two special cases. * 1. If we're at the root directory (e.g. after chroot or * zone_enter) then change ".." to "." so we can't get * out of this subtree. * 2. If this vnode is the root of a mounted file system, * then replace it with the vnode that was mounted on * so that we take the ".." in the other file system. */ if (component[0] == '.' && component[1] == '.' && component[2] == 0) { checkforroot: if (VN_CMP(vp, rootvp) || VN_CMP(vp, zonevp)) { component[1] = '\0'; } else if (vp->v_flag & VROOT) { vfs_t *vfsp; cvp = vp; /* * While we deal with the vfs pointer from the vnode * the filesystem could have been forcefully unmounted * and the vnode's v_vfsp could have been invalidated * by VFS_UNMOUNT. Hence, we cache v_vfsp and use it * with vfs_rlock_wait/vfs_unlock. * It is safe to use the v_vfsp even it is freed by * VFS_UNMOUNT because vfs_rlock_wait/vfs_unlock * do not dereference v_vfsp. It is just used as a * magic cookie. * One more corner case here is the memory getting * reused for another vfs structure. In this case * lookuppnvp's vfs_rlock_wait will succeed, domount's * vfs_lock will fail and domount will bail out with an * error (EBUSY). */ vfsp = cvp->v_vfsp; /* * This lock is used to synchronize * mounts/unmounts and lookups. * Threads doing mounts/unmounts hold the * writers version vfs_lock_wait(). */ vfs_rlock_wait(vfsp); /* * If this vnode is on a file system that * has been forcibly unmounted, * we can't proceed. Cancel this operation * and return EIO. * * vfs_vnodecovered is NULL if unmounted. * Currently, nfs uses VFS_UNMOUNTED to * check if it's a forced-umount. Keep the * same checking here as well even though it * may not be needed. */ if (((vp = cvp->v_vfsp->vfs_vnodecovered) == NULL) || (cvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)) { vfs_unlock(vfsp); VN_RELE(cvp); if (pp) pn_free(pp); return (EIO); } VN_HOLD(vp); vfs_unlock(vfsp); VN_RELE(cvp); cvp = NULL; /* * Crossing mount points. For eg: We are doing * a lookup of ".." for file systems root vnode * mounted here, and VOP_LOOKUP() (with covered vnode) * will be on underlying file systems mount point * vnode. Set retry_with_kcred flag as we might end * up doing VOP_LOOKUP() with kcred if required. */ retry_with_kcred = B_TRUE; goto checkforroot; } } /* * LOOKUP_CHECKREAD is a private flag used by vnodetopath() to indicate * that we need to have read permission on every directory in the entire * path. This is used to ensure that a forward-lookup of a cached value * has the same effect as a reverse-lookup when the cached value cannot * be found. */ if ((flags & LOOKUP_CHECKREAD) && (error = VOP_ACCESS(vp, VREAD, 0, cr, NULL)) != 0) goto bad; /* * Perform a lookup in the current directory. */ error = VOP_LOOKUP(vp, component, &cvp, pnp, lookup_flags, rootvp, cr, NULL, NULL, pp); /* * Retry with kcred - If crossing mount points & error is EACCES. * * If we are crossing mount points here and doing ".." lookup, * VOP_LOOKUP() might fail if the underlying file systems * mount point has no execute permission. In cases like these, * we retry VOP_LOOKUP() by giving as much privilage as possible * by passing kcred credentials. * * In case of hierarchical file systems, passing kcred still may * or may not work. * For eg: UFS FS --> Mount NFS FS --> Again mount UFS on some * directory inside NFS FS. */ if ((error == EACCES) && retry_with_kcred) error = VOP_LOOKUP(vp, component, &cvp, pnp, lookup_flags, rootvp, zone_kcred(), NULL, NULL, pp); if (error) { cvp = NULL; /* * On error, return hard error if * (a) we're not at the end of the pathname yet, or * (b) the caller didn't want the parent directory, or * (c) we failed for some reason other than a missing entry. */ if (pn_pathleft(pnp) || dirvpp == NULL || error != ENOENT) goto bad; if (auditing) { /* directory access */ if (error = audit_savepath(pnp, vp, vp, error, cr)) goto bad_noaudit; } pn_setlast(pnp); /* * We inform the caller that the desired entry must be * a directory by adding a '/' to the component name. */ if (must_be_directory && (error = pn_addslash(pnp)) != 0) goto bad; *dirvpp = vp; if (compvpp != NULL) *compvpp = NULL; if (rootvp != rootdir) VN_RELE(rootvp); if (pp) pn_free(pp); return (0); } /* * Traverse mount points. * XXX why don't we need to hold a read lock here (call vn_vfsrlock)? * What prevents a concurrent update to v_vfsmountedhere? * Possible answer: if mounting, we might not see the mount * if it is concurrently coming into existence, but that's * really not much different from the thread running a bit slower. * If unmounting, we may get into traverse() when we shouldn't, * but traverse() will catch this case for us. * (For this to work, fetching v_vfsmountedhere had better * be atomic!) */ if (vn_mountedvfs(cvp) != NULL) { if ((error = traverse(&cvp)) != 0) goto bad; } /* * If we hit a symbolic link and there is more path to be * translated or this operation does not wish to apply * to a link, then place the contents of the link at the * front of the remaining pathname. */ if (cvp->v_type == VLNK && ((flags & FOLLOW) || pn_pathleft(pnp))) { struct pathname linkpath; if (++nlink > MAXSYMLINKS) { error = ELOOP; goto bad; } pn_alloc(&linkpath); if (error = pn_getsymlink(cvp, &linkpath, cr)) { pn_free(&linkpath); goto bad; } if (auditing) audit_symlink(pnp, &linkpath); if (pn_pathleft(&linkpath) == 0) (void) pn_set(&linkpath, "."); error = pn_insert(pnp, &linkpath, strlen(component)); pn_free(&linkpath); if (error) goto bad; VN_RELE(cvp); cvp = NULL; if (pnp->pn_pathlen == 0) { error = ENOENT; goto bad; } if (pnp->pn_path[0] == '/') { do { pnp->pn_path++; pnp->pn_pathlen--; } while (pnp->pn_path[0] == '/'); VN_RELE(vp); vp = rootvp; VN_HOLD(vp); } if (auditing) audit_anchorpath(pnp, vp == rootvp); if (pn_fixslash(pnp)) { flags |= FOLLOW; must_be_directory = 1; } goto next; } /* * If rpnp is non-NULL, remember the resolved path name therein. * Do not include "." components. Collapse occurrences of * "previous/..", so long as "previous" is not itself "..". * Exhausting rpnp results in error ENAMETOOLONG. */ if (rpnp && strcmp(component, ".") != 0) { size_t len; if (strcmp(component, "..") == 0 && rpnp->pn_pathlen != 0 && !((rpnp->pn_pathlen > 2 && strncmp(rpnp->pn_path+rpnp->pn_pathlen-3, "/..", 3) == 0) || (rpnp->pn_pathlen == 2 && strncmp(rpnp->pn_path, "..", 2) == 0))) { while (rpnp->pn_pathlen && rpnp->pn_path[rpnp->pn_pathlen-1] != '/') rpnp->pn_pathlen--; if (rpnp->pn_pathlen > 1) rpnp->pn_pathlen--; rpnp->pn_path[rpnp->pn_pathlen] = '\0'; } else { if (rpnp->pn_pathlen != 0 && rpnp->pn_path[rpnp->pn_pathlen-1] != '/') rpnp->pn_path[rpnp->pn_pathlen++] = '/'; if (flags & FIGNORECASE) { /* * Return the case-preserved name * within the resolved path. */ error = copystr(pp->pn_buf, rpnp->pn_path + rpnp->pn_pathlen, rpnp->pn_bufsize - rpnp->pn_pathlen, &len); } else { error = copystr(component, rpnp->pn_path + rpnp->pn_pathlen, rpnp->pn_bufsize - rpnp->pn_pathlen, &len); } if (error) /* copystr() returns ENAMETOOLONG */ goto bad; rpnp->pn_pathlen += (len - 1); ASSERT(rpnp->pn_bufsize > rpnp->pn_pathlen); } } /* * If no more components, return last directory (if wanted) and * last component (if wanted). */ if (pn_pathleft(pnp) == 0) { /* * If there was a trailing slash in the pathname, * make sure the last component is a directory. */ if (must_be_directory && cvp->v_type != VDIR) { error = ENOTDIR; goto bad; } if (dirvpp != NULL) { /* * Check that we have the real parent and not * an alias of the last component. */ if (vn_compare(vp, cvp)) { if (auditing) (void) audit_savepath(pnp, cvp, vp, EINVAL, cr); pn_setlast(pnp); VN_RELE(vp); VN_RELE(cvp); if (rootvp != rootdir) VN_RELE(rootvp); if (pp) pn_free(pp); return (EINVAL); } *dirvpp = vp; } else VN_RELE(vp); if (auditing) (void) audit_savepath(pnp, cvp, vp, 0, cr); if (pnp->pn_path == pnp->pn_buf) (void) pn_set(pnp, "."); else pn_setlast(pnp); if (rpnp) { if (VN_CMP(cvp, rootvp)) (void) pn_set(rpnp, "/"); else if (rpnp->pn_pathlen == 0) (void) pn_set(rpnp, "."); } if (compvpp != NULL) *compvpp = cvp; else VN_RELE(cvp); if (rootvp != rootdir) VN_RELE(rootvp); if (pp) pn_free(pp); return (0); } /* * Skip over slashes from end of last component. */ while (pnp->pn_path[0] == '/') { pnp->pn_path++; pnp->pn_pathlen--; } /* * Searched through another level of directory: * release previous directory handle and save new (result * of lookup) as current directory. */ VN_RELE(vp); vp = cvp; cvp = NULL; goto next; bad: if (auditing) /* reached end of path */ (void) audit_savepath(pnp, cvp, vp, error, cr); bad_noaudit: /* * Error. Release vnodes and return. */ if (cvp) VN_RELE(cvp); /* * If the error was ESTALE and the current directory to look in * was the root for this lookup, the root for a mounted file * system, or the starting directory for lookups, then * return ENOENT instead of ESTALE. In this case, no recovery * is possible by the higher level. If ESTALE was returned for * some intermediate directory along the path, then recovery * is potentially possible and retrying from the higher level * will either correct the situation by purging stale cache * entries or eventually get back to the point where no recovery * is possible. */ if (error == ESTALE && (VN_CMP(vp, rootvp) || (vp->v_flag & VROOT) || vp == startvp)) error = ENOENT; VN_RELE(vp); if (rootvp != rootdir) VN_RELE(rootvp); if (pp) pn_free(pp); return (error); }
/* * VFS Operations. * * mount system call */ int ext2fs_mount(struct mount *mp, const char *path, void *data, size_t *data_len) { struct lwp *l = curlwp; struct vnode *devvp; struct ufs_args *args = data; struct ufsmount *ump = NULL; struct m_ext2fs *fs; size_t size; int error = 0, flags, update; mode_t accessmode; if (*data_len < sizeof *args) return EINVAL; if (mp->mnt_flag & MNT_GETARGS) { ump = VFSTOUFS(mp); if (ump == NULL) return EIO; memset(args, 0, sizeof *args); args->fspec = NULL; *data_len = sizeof *args; return 0; } update = mp->mnt_flag & MNT_UPDATE; /* Check arguments */ if (args->fspec != NULL) { /* * Look up the name and verify that it's sane. */ error = namei_simple_user(args->fspec, NSM_FOLLOW_NOEMULROOT, &devvp); if (error != 0) return (error); if (!update) { /* * Be sure this is a valid block device */ if (devvp->v_type != VBLK) error = ENOTBLK; else if (bdevsw_lookup(devvp->v_rdev) == NULL) error = ENXIO; } else { /* * Be sure we're still naming the same device * used for our initial mount */ ump = VFSTOUFS(mp); if (devvp != ump->um_devvp) { if (devvp->v_rdev != ump->um_devvp->v_rdev) error = EINVAL; else { vrele(devvp); devvp = ump->um_devvp; vref(devvp); } } } } else { if (!update) { /* New mounts must have a filename for the device */ return (EINVAL); } else { ump = VFSTOUFS(mp); devvp = ump->um_devvp; vref(devvp); } } /* * If mount by non-root, then verify that user has necessary * permissions on the device. * * Permission to update a mount is checked higher, so here we presume * updating the mount is okay (for example, as far as securelevel goes) * which leaves us with the normal check. */ if (error == 0) { accessmode = VREAD; if (update ? (mp->mnt_iflag & IMNT_WANTRDWR) != 0 : (mp->mnt_flag & MNT_RDONLY) == 0) accessmode |= VWRITE; vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_MOUNT, KAUTH_REQ_SYSTEM_MOUNT_DEVICE, mp, devvp, KAUTH_ARG(accessmode)); VOP_UNLOCK(devvp); } if (error) { vrele(devvp); return (error); } if (!update) { int xflags; if (mp->mnt_flag & MNT_RDONLY) xflags = FREAD; else xflags = FREAD|FWRITE; vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); error = VOP_OPEN(devvp, xflags, FSCRED); VOP_UNLOCK(devvp); if (error) goto fail; error = ext2fs_mountfs(devvp, mp); if (error) { vn_lock(devvp, LK_EXCLUSIVE | LK_RETRY); (void)VOP_CLOSE(devvp, xflags, NOCRED); VOP_UNLOCK(devvp); goto fail; } ump = VFSTOUFS(mp); fs = ump->um_e2fs; } else { /* * Update the mount. */ /* * The initial mount got a reference on this * device, so drop the one obtained via * namei(), above. */ vrele(devvp); ump = VFSTOUFS(mp); fs = ump->um_e2fs; if (fs->e2fs_ronly == 0 && (mp->mnt_flag & MNT_RDONLY)) { /* * Changing from r/w to r/o */ flags = WRITECLOSE; if (mp->mnt_flag & MNT_FORCE) flags |= FORCECLOSE; error = ext2fs_flushfiles(mp, flags); if (error == 0 && ext2fs_cgupdate(ump, MNT_WAIT) == 0 && (fs->e2fs.e2fs_state & E2FS_ERRORS) == 0) { fs->e2fs.e2fs_state = E2FS_ISCLEAN; (void) ext2fs_sbupdate(ump, MNT_WAIT); } if (error) return (error); fs->e2fs_ronly = 1; } if (mp->mnt_flag & MNT_RELOAD) { error = ext2fs_reload(mp, l->l_cred, l); if (error) return (error); } if (fs->e2fs_ronly && (mp->mnt_iflag & IMNT_WANTRDWR)) { /* * Changing from read-only to read/write */ fs->e2fs_ronly = 0; if (fs->e2fs.e2fs_state == E2FS_ISCLEAN) fs->e2fs.e2fs_state = 0; else fs->e2fs.e2fs_state = E2FS_ERRORS; fs->e2fs_fmod = 1; } if (args->fspec == NULL) return 0; } error = set_statvfs_info(path, UIO_USERSPACE, args->fspec, UIO_USERSPACE, mp->mnt_op->vfs_name, mp, l); (void) copystr(mp->mnt_stat.f_mntonname, fs->e2fs_fsmnt, sizeof(fs->e2fs_fsmnt) - 1, &size); memset(fs->e2fs_fsmnt + size, 0, sizeof(fs->e2fs_fsmnt) - size); if (fs->e2fs.e2fs_rev > E2FS_REV0) { (void) copystr(mp->mnt_stat.f_mntonname, fs->e2fs.e2fs_fsmnt, sizeof(fs->e2fs.e2fs_fsmnt) - 1, &size); memset(fs->e2fs.e2fs_fsmnt, 0, sizeof(fs->e2fs.e2fs_fsmnt) - size); } if (fs->e2fs_fmod != 0) { /* XXX */ fs->e2fs_fmod = 0; if (fs->e2fs.e2fs_state == 0) fs->e2fs.e2fs_wtime = time_second; else printf("%s: file system not clean; please fsck(8)\n", mp->mnt_stat.f_mntfromname); (void) ext2fs_cgupdate(ump, MNT_WAIT); } return (error); fail: vrele(devvp); return (error); }
static struct parseNode *getParseTreeMethod(struct parserState *ps) { int y=getToken(ps); struct parseNode *result,*next,*ptr,*type,*arg; result=newNode(11); result->lineno=ps->lineno; if(y==NameToken) { next=newNode(5); next->lineno=ps->lineno; result->dat.n=next; ptr=next; type=newNode(0); type->lineno=ps->lineno; type->dat.s=copystr(ps->token); next->dat.n=type; y=getToken(ps); if(y==NameToken) { arg=newNode(0); arg->lineno=ps->lineno; arg->dat.s=copystr(ps->token); type->next=arg; y=getToken(ps); } else { error("Error! Missing type name or argument type at %d, found %s\n", ps->lineno,ps->token); return result; } while(y!=NoMoreToken && ps->token[0]!=')') { if(ps->token[0]!=',') { error("Error! Expected ',' or ';' before %s at %d\n", ps->token,ps->lineno); return result; } y=getToken(ps); if(y!=NameToken) { error("Error! Missing type name or argument type at %d, found %s\n", ps->lineno,ps->token); return result; } next=newNode(5); next->lineno=ps->lineno; ptr->next=next; ptr=next; type=newNode(0); type->lineno=ps->lineno; type->dat.s=copystr(ps->token); next->dat.n=type; y=getToken(ps); if(y==NameToken) { arg=newNode(0); arg->lineno=ps->lineno; arg->dat.s=copystr(ps->token); type->next=arg; } else { error("Error! Missing type name or argument type at %d, found %s\n", ps->lineno,ps->token); return result; } y=getToken(ps); } } y=getToken(ps); if(ps->token[0]!='{') { error("Error! Left bracket { expected at %d, found %s\n" ,ps->lineno,ps->token); return result; } result->next=getParseTreeBlock(ps,2); result->next->dat.n=repairPTStmt(result->next->dat.n); state=getToken(ps); return result; }
static struct parseNode *getParseTreeClass(struct parserState *ps) { int y; char *name,*baseName=NULL; y=getToken(ps); if(y==NoMoreToken) return NULL; if(strcmp(ps->token,"class")!=0) { error("Error! OOPS only supports classes. Unexpected token %s at %d\n", ps->token,ps->lineno); return NULL; } struct parseNode *result,*next,*ptr,*cc; result=newNode(1); result->lineno=ps->lineno; y=getToken(ps); if(y==NoMoreToken || y!=NameToken) { error("Error! Class name expected at line %d\n",ps->lineno); return NULL; } name=copystr(ps->token); next=newNode(3); next->lineno=ps->lineno; cc=newNode(0); next->dat.n=cc; cc->lineno=ps->lineno; cc->dat.s=name; result->dat.n=next; ptr=next; y=getToken(ps); if(y!=NoMoreToken && strcmp(ps->token,":")==0) { y=getToken(ps); if(y!=NameToken) { error("Error! Base class name expected at line %d\n",ps->lineno); return result; } baseName=copystr(ps->token); cc=newNode(0); cc->lineno=ps->lineno; cc->dat.s=baseName; next->dat.n->next=cc; y=getToken(ps); } if(y!=NoMoreToken && strcmp(ps->token,"{")==0) { y=getToken(ps); if(y!=NameToken && strcmp(ps->token,"}")!=0) { error("Error! Method or variable definition expected at %d\n",ps->lineno); return result; } next=getParseTreeVar(ps); state=NameToken; while(next!=NULL) { ptr->next=next; ptr=next; ptr->next=NULL; if(errorOccured) { return result; } next=getParseTreeVar(ps); } if(strcmp(ps->token,"}")!=0) { if(state==NoMoreToken) error("Error! Missing right brace } at line %d\n",ps->lineno); else if(state!=NameToken) error("Error! Method or variable definition expected at %d\n",ps->lineno); } } else { error("Error! Left brace { expected at line %d\n",ps->lineno); return result; } return result; }
/*-----------------------------------------------------------------------------------*/ static char * loadtheme(char *str) { return copystr(theme, str, sizeof(theme)); }
/*-----------------------------------------------------------------------------------*/ static char * loadcfs(char *str) { return copystr(cfs, str, sizeof(cfs)); }
/* * Mount system call */ static int reiserfs_mount(struct mount *mp) { size_t size; int error, len; accmode_t accmode; char *path, *fspec; struct vnode *devvp; struct vfsoptlist *opts; struct reiserfs_mount *rmp; struct reiserfs_sb_info *sbi; struct nameidata nd, *ndp = &nd; struct thread *td; td = curthread; if (!(mp->mnt_flag & MNT_RDONLY)) return EROFS; /* Get the new options passed to mount */ opts = mp->mnt_optnew; /* `fspath' contains the mount point (eg. /mnt/linux); REQUIRED */ vfs_getopt(opts, "fspath", (void **)&path, NULL); reiserfs_log(LOG_INFO, "mount point is `%s'\n", path); /* `from' contains the device name (eg. /dev/ad0s1); REQUIRED */ fspec = NULL; error = vfs_getopt(opts, "from", (void **)&fspec, &len); if (!error && fspec[len - 1] != '\0') return (EINVAL); reiserfs_log(LOG_INFO, "device is `%s'\n", fspec); /* Handle MNT_UPDATE (mp->mnt_flag) */ if (mp->mnt_flag & MNT_UPDATE) { /* For now, only NFS export is supported. */ if (vfs_flagopt(opts, "export", NULL, 0)) return (0); } /* Not an update, or updating the name: look up the name * and verify that it refers to a sensible disk device. */ if (fspec == NULL) return (EINVAL); NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspec, td); if ((error = namei(ndp)) != 0) return (error); NDFREE(ndp, NDF_ONLY_PNBUF); devvp = ndp->ni_vp; if (!vn_isdisk(devvp, &error)) { vput(devvp); return (error); } /* If mount by non-root, then verify that user has necessary * permissions on the device. */ accmode = VREAD; if ((mp->mnt_flag & MNT_RDONLY) == 0) accmode |= VWRITE; error = VOP_ACCESS(devvp, accmode, td->td_ucred, td); if (error) error = priv_check(td, PRIV_VFS_MOUNT_PERM); if (error) { vput(devvp); return (error); } if ((mp->mnt_flag & MNT_UPDATE) == 0) { error = reiserfs_mountfs(devvp, mp, td); } else { /* TODO Handle MNT_UPDATE */ vput(devvp); return (EOPNOTSUPP); } if (error) { vrele(devvp); return (error); } rmp = VFSTOREISERFS(mp); sbi = rmp->rm_reiserfs; /* * Note that this strncpy() is ok because of a check at the start * of reiserfs_mount(). */ reiserfs_log(LOG_DEBUG, "prepare statfs data\n"); (void)copystr(fspec, mp->mnt_stat.f_mntfromname, MNAMELEN - 1, &size); bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size); (void)reiserfs_statfs(mp, &mp->mnt_stat); reiserfs_log(LOG_DEBUG, "done\n"); return (0); }
/*-----------------------------------------------------------------------------------*/ static char * loaddriver(char *str) { return copystr(driver, str, sizeof(driver)); }
static HCACHEFILE* hcachefile_get(TARGET *t) { HCACHEFILE filedata, *file = &filedata; SETTINGS *vars; const char *hcachename = NULL; if ( t->flags & T_FLAG_USEDEPCACHE ) { for ( vars = t->settings; vars; vars = vars->next ) { if ( vars->symbol[0] == 'D' && strcmp( vars->symbol, "DEPCACHE" ) == 0 ) { hcachename = list_value(list_first(vars->value)); break; } } } if ( !hcachename ) { LIST *hcache = var_get( "DEPCACHE" ); if ( list_first(hcache) ) hcachename = list_value(list_first(hcache)); } if ( !hcachename ) { hcachename = newstr( "standard" ); } if (lasthcachefile_name == hcachename) return lasthcachefile; filedata.cachename = hcachename; if ( !hcachefilehash ) { hcachefilehash = hashinit( sizeof( HCACHEFILE ), "hcachefile" ); } if( !hashcheck( hcachefilehash, (HASHDATA **) &file ) ) { if( hashenter( hcachefilehash, (HASHDATA **)&file ) ) { char varBuffer[ MAXJPATH ]; LIST *hcachevar; file->cachefilename = 0; file->hcachehash = hashinit( sizeof( HCACHEDATA ), "hcache" ); file->hcachelist = 0; file->next = hcachefilelist; file->dirty = 0; hcachefilelist = file; strcpy( varBuffer, "DEPCACHE." ); strcat( varBuffer, hcachename ); hcachevar = var_get( varBuffer ); if( list_first(hcachevar) ) { TARGET *t = bindtarget(list_value(list_first(hcachevar))); t->boundname = search_using_target_settings( t, t->name, &t->time ); file->cachefilename = copystr( t->boundname ); hcache_readfile( file ); } } } lasthcachefile = file; lasthcachefile_name = file->cachename; return lasthcachefile; }
/* * Function: devfs_kernel_mount * Purpose: * Mount devfs at the given mount point from within the kernel. */ int devfs_kernel_mount(char * mntname) { struct mount *mp; int error; struct nameidata nd; struct vnode * vp; vfs_context_t ctx = vfs_context_kernel(); struct vfstable *vfsp; /* Find our vfstable entry */ for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) if (!strncmp(vfsp->vfc_name, "devfs", sizeof(vfsp->vfc_name))) break; if (!vfsp) { panic("Could not find entry in vfsconf for devfs.\n"); } /* * Get vnode to be covered */ NDINIT(&nd, LOOKUP, OP_MOUNT, FOLLOW | LOCKLEAF, UIO_SYSSPACE, CAST_USER_ADDR_T(mntname), ctx); if ((error = namei(&nd))) { printf("devfs_kernel_mount: failed to find directory '%s', %d", mntname, error); return (error); } nameidone(&nd); vp = nd.ni_vp; if ((error = VNOP_FSYNC(vp, MNT_WAIT, ctx))) { printf("devfs_kernel_mount: vnop_fsync failed: %d\n", error); vnode_put(vp); return (error); } if ((error = buf_invalidateblks(vp, BUF_WRITE_DATA, 0, 0))) { printf("devfs_kernel_mount: buf_invalidateblks failed: %d\n", error); vnode_put(vp); return (error); } if (vnode_isdir(vp) == 0) { printf("devfs_kernel_mount: '%s' is not a directory\n", mntname); vnode_put(vp); return (ENOTDIR); } if ((vnode_mountedhere(vp))) { vnode_put(vp); return (EBUSY); } /* * Allocate and initialize the filesystem. */ MALLOC_ZONE(mp, struct mount *, sizeof(struct mount), M_MOUNT, M_WAITOK); bzero((char *)mp, sizeof(struct mount)); /* Initialize the default IO constraints */ mp->mnt_maxreadcnt = mp->mnt_maxwritecnt = MAXPHYS; mp->mnt_segreadcnt = mp->mnt_segwritecnt = 32; mp->mnt_ioflags = 0; mp->mnt_realrootvp = NULLVP; mp->mnt_authcache_ttl = CACHED_LOOKUP_RIGHT_TTL; mount_lock_init(mp); TAILQ_INIT(&mp->mnt_vnodelist); TAILQ_INIT(&mp->mnt_workerqueue); TAILQ_INIT(&mp->mnt_newvnodes); (void)vfs_busy(mp, LK_NOWAIT); mp->mnt_op = &devfs_vfsops; mp->mnt_vtable = vfsp; mp->mnt_flag = 0; mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; strlcpy(mp->mnt_vfsstat.f_fstypename, vfsp->vfc_name, MFSTYPENAMELEN); vp->v_mountedhere = mp; mp->mnt_vnodecovered = vp; mp->mnt_vfsstat.f_owner = kauth_cred_getuid(kauth_cred_get()); (void) copystr(mntname, mp->mnt_vfsstat.f_mntonname, MAXPATHLEN - 1, 0); #if CONFIG_MACF mac_mount_label_init(mp); mac_mount_label_associate(ctx, mp); #endif error = devfs_mount(mp, NULL, USER_ADDR_NULL, ctx); if (error) { printf("devfs_kernel_mount: mount %s failed: %d", mntname, error); mp->mnt_vtable->vfc_refcount--; vfs_unbusy(mp); mount_lock_destroy(mp); #if CONFIG_MACF mac_mount_label_destroy(mp); #endif FREE_ZONE(mp, sizeof (struct mount), M_MOUNT); vnode_put(vp); return (error); } vnode_ref(vp); vnode_put(vp); vfs_unbusy(mp); mount_list_add(mp); return (0); }
/* * Function to call when a host responds. It would also be appropriate * if the responses are asynchronous but the host returns an error on * the initial call to handle_request * * If passed with error_number != 0 the result will be * interpreted as an error. Otherwise it is interpreted as a * response. */ int host_responded( char *job_id, char *host, int host_num, int error_number, char *result) { samrthread_t *ptr; dispatch_job_t *dj; /* result is checked for NULL later */ if (ISNULL(job_id, host)) { Trace(TR_ERR, "failed to find the job: %d %s", samerrno, samerrmsg); return (-1); } Trace(TR_DEBUG, "updating dispatch job %s with response from %s", job_id, host); pthread_mutex_lock(samrlock); /* ++ LOCK samrtlist */ ptr = find_this_activity(job_id); if (ptr == NULL) { pthread_mutex_unlock(samrlock); /* ++ UNLOCK */ Trace(TR_ERR, "failed to find the job: %d %s", samerrno, samerrmsg); return (samrerr(SE_NO_SUCH_ACTIVITY, job_id)); } dj = (dispatch_job_t *)ptr->args->db.job; /* Set the error or response for the current host in the job */ if (host_num < dj->host_count) { /* Increment the hosts that have responded */ dj->hosts_responded++; dj->responses[host_num].error = error_number; if (error_number == 0) { dj->responses[host_num].status = OP_SUCCEEDED; } else { dj->responses[host_num].status = OP_FAILED; } /* A result is not mandatory */ if (result != NULL) { dj->responses[host_num].result = copystr(result); if (dj->responses[host_num].result == NULL) { pthread_mutex_unlock(samrlock); /* ++ UNLOCK */ Trace(TR_ERR, "error duplicating result: %d %s", samerrno, samerrmsg); return (-1); } } } else { pthread_mutex_unlock(samrlock); /* ++ UNLOCK */ Trace(TR_ERR, "Host number outside of range"); setsamerr(SE_INVALID_HOST_ID_IN_RESPONSE); return (-1); } /* * If all hosts have responded, call the post_phase handler to do any * necessary work on this host and set the end time and * overall status. */ if (dj->hosts_responded == dj->host_count) { if (dj->post_phase != NULL) { int ret; dj->overall_status = DJ_POST_PHASE_PENDING; /* * It would be good to do the post phase handling * with the mutex unlocked but it is not currently * safe to do so. */ ret = dj->post_phase(dj); /* Set status */ if (ret == -1) { dj->overall_status = DJ_POST_PHASE_FAILED; dj->overall_error_num = samerrno; dj->overall_error_msg = copystr(samerrmsg); } else { dj->overall_status = DJ_POST_PHASE_SUCCEEDED; } dj->endtime = time(0); } else { dj->overall_status = DJ_DONE; dj->endtime = time(0); } } pthread_mutex_unlock(samrlock); /* ++ UNLOCK */ return (0); }
/* * Search an alternate path before passing pathname arguments on * to system calls. Useful for keeping a separate 'emulation tree'. * * If cflag is set, we check if an attempt can be made to create * the named file, i.e. we check if the directory it should * be in exists. */ int emul_find(struct proc *p, caddr_t *sgp, const char *prefix, char *path, char **pbuf, int cflag) { struct nameidata nd; struct nameidata ndroot; struct vattr vat; struct vattr vatroot; int error; char *ptr, *buf, *cp; const char *pr; size_t sz, len; buf = (char *) malloc(MAXPATHLEN, M_TEMP, M_WAITOK); *pbuf = path; for (ptr = buf, pr = prefix; (*ptr = *pr) != '\0'; ptr++, pr++) continue; sz = MAXPATHLEN - (ptr - buf); /* * If sgp is not given then the path is already in kernel space */ if (sgp == NULL) error = copystr(path, ptr, sz, &len); else error = copyinstr(path, ptr, sz, &len); if (error) goto bad; if (*ptr != '/') { error = EINVAL; goto bad; } /* * We know that there is a / somewhere in this pathname. * Search backwards for it, to find the file's parent dir * to see if it exists in the alternate tree. If it does, * and we want to create a file (cflag is set). We don't * need to worry about the root comparison in this case. */ if (cflag) { for (cp = &ptr[len] - 1; *cp != '/'; cp--) ; *cp = '\0'; NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, p); if ((error = namei(&nd)) != 0) goto bad; *cp = '/'; } else { NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, buf, p); if ((error = namei(&nd)) != 0) goto bad; /* * We now compare the vnode of the emulation root to the one * vnode asked. If they resolve to be the same, then we * ignore the match so that the real root gets used. * This avoids the problem of traversing "../.." to find the * root directory and never finding it, because "/" resolves * to the emulation root directory. This is expensive :-( */ /* XXX: prototype should have const here for NDINIT */ NDINIT(&ndroot, LOOKUP, FOLLOW, UIO_SYSSPACE, prefix, p); if ((error = namei(&ndroot)) != 0) goto bad2; if ((error = VOP_GETATTR(nd.ni_vp, &vat, p->p_ucred, p)) != 0) goto bad3; if ((error = VOP_GETATTR(ndroot.ni_vp, &vatroot, p->p_ucred, p)) != 0) goto bad3; if (vat.va_fsid == vatroot.va_fsid && vat.va_fileid == vatroot.va_fileid) { error = ENOENT; goto bad3; } } if (sgp == NULL) *pbuf = buf; else { sz = &ptr[len] - buf; *pbuf = stackgap_alloc(sgp, sz + 1); if (*pbuf == NULL) { error = ENAMETOOLONG; goto bad; } if ((error = copyout(buf, *pbuf, sz)) != 0) { *pbuf = path; goto bad; } free(buf, M_TEMP); } vrele(nd.ni_vp); if (!cflag) vrele(ndroot.ni_vp); return error; bad3: vrele(ndroot.ni_vp); bad2: vrele(nd.ni_vp); bad: free(buf, M_TEMP); return error; }
/*-----------------------------------------------------------------------------------*/ static char * loadscreensaver(char *str) { return copystr(screensaver, str, sizeof(screensaver)); }
/* * Mount unionfs layer. */ static int unionfs_domount(struct mount *mp) { int error; struct vnode *lowerrootvp; struct vnode *upperrootvp; struct unionfs_mount *ump; struct thread *td; char *target; char *tmp; char *ep; int len; size_t done; int below; uid_t uid; gid_t gid; u_short udir; u_short ufile; unionfs_copymode copymode; unionfs_whitemode whitemode; struct componentname fakecn; struct nameidata nd, *ndp; struct vattr va; UNIONFSDEBUG("unionfs_mount(mp = %p)\n", (void *)mp); error = 0; below = 0; uid = 0; gid = 0; udir = 0; ufile = 0; copymode = UNIONFS_TRANSPARENT; /* default */ whitemode = UNIONFS_WHITE_ALWAYS; ndp = &nd; td = curthread; if (mp->mnt_flag & MNT_ROOTFS) { vfs_mount_error(mp, "Cannot union mount root filesystem"); return (EOPNOTSUPP); } /* * Update is a no operation. */ if (mp->mnt_flag & MNT_UPDATE) { vfs_mount_error(mp, "unionfs does not support mount update"); return (EOPNOTSUPP); } /* * Get argument */ error = vfs_getopt(mp->mnt_optnew, "target", (void **)&target, &len); if (error) error = vfs_getopt(mp->mnt_optnew, "from", (void **)&target, &len); if (error || target[len - 1] != '\0') { vfs_mount_error(mp, "Invalid target"); return (EINVAL); } if (vfs_getopt(mp->mnt_optnew, "below", NULL, NULL) == 0) below = 1; if (vfs_getopt(mp->mnt_optnew, "udir", (void **)&tmp, NULL) == 0) { if (tmp != NULL) udir = (mode_t)strtol(tmp, &ep, 8); if (tmp == NULL || *ep) { vfs_mount_error(mp, "Invalid udir"); return (EINVAL); } udir &= S_IRWXU | S_IRWXG | S_IRWXO; } if (vfs_getopt(mp->mnt_optnew, "ufile", (void **)&tmp, NULL) == 0) { if (tmp != NULL) ufile = (mode_t)strtol(tmp, &ep, 8); if (tmp == NULL || *ep) { vfs_mount_error(mp, "Invalid ufile"); return (EINVAL); } ufile &= S_IRWXU | S_IRWXG | S_IRWXO; } /* check umask, uid and gid */ if (udir == 0 && ufile != 0) udir = ufile; if (ufile == 0 && udir != 0) ufile = udir; vn_lock(mp->mnt_vnodecovered, LK_SHARED | LK_RETRY); error = VOP_GETATTR(mp->mnt_vnodecovered, &va, mp->mnt_cred); if (!error) { if (udir == 0) udir = va.va_mode; if (ufile == 0) ufile = va.va_mode; uid = va.va_uid; gid = va.va_gid; } VOP_UNLOCK(mp->mnt_vnodecovered, 0); if (error) return (error); if (mp->mnt_cred->cr_ruid == 0) { /* root only */ if (vfs_getopt(mp->mnt_optnew, "uid", (void **)&tmp, NULL) == 0) { if (tmp != NULL) uid = (uid_t)strtol(tmp, &ep, 10); if (tmp == NULL || *ep) { vfs_mount_error(mp, "Invalid uid"); return (EINVAL); } } if (vfs_getopt(mp->mnt_optnew, "gid", (void **)&tmp, NULL) == 0) { if (tmp != NULL) gid = (gid_t)strtol(tmp, &ep, 10); if (tmp == NULL || *ep) { vfs_mount_error(mp, "Invalid gid"); return (EINVAL); } } if (vfs_getopt(mp->mnt_optnew, "copymode", (void **)&tmp, NULL) == 0) { if (tmp == NULL) { vfs_mount_error(mp, "Invalid copymode"); return (EINVAL); } else if (strcasecmp(tmp, "traditional") == 0) copymode = UNIONFS_TRADITIONAL; else if (strcasecmp(tmp, "transparent") == 0) copymode = UNIONFS_TRANSPARENT; else if (strcasecmp(tmp, "masquerade") == 0) copymode = UNIONFS_MASQUERADE; else { vfs_mount_error(mp, "Invalid copymode"); return (EINVAL); } } if (vfs_getopt(mp->mnt_optnew, "whiteout", (void **)&tmp, NULL) == 0) { if (tmp == NULL) { vfs_mount_error(mp, "Invalid whiteout mode"); return (EINVAL); } else if (strcasecmp(tmp, "always") == 0) whitemode = UNIONFS_WHITE_ALWAYS; else if (strcasecmp(tmp, "whenneeded") == 0) whitemode = UNIONFS_WHITE_WHENNEEDED; else { vfs_mount_error(mp, "Invalid whiteout mode"); return (EINVAL); } } } /* If copymode is UNIONFS_TRADITIONAL, uid/gid is mounted user. */ if (copymode == UNIONFS_TRADITIONAL) { uid = mp->mnt_cred->cr_ruid; gid = mp->mnt_cred->cr_rgid; } UNIONFSDEBUG("unionfs_mount: uid=%d, gid=%d\n", uid, gid); UNIONFSDEBUG("unionfs_mount: udir=0%03o, ufile=0%03o\n", udir, ufile); UNIONFSDEBUG("unionfs_mount: copymode=%d\n", copymode); /* * Find upper node */ NDINIT(ndp, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, target, td); if ((error = namei(ndp))) return (error); NDFREE(ndp, NDF_ONLY_PNBUF); /* get root vnodes */ lowerrootvp = mp->mnt_vnodecovered; upperrootvp = ndp->ni_vp; /* create unionfs_mount */ ump = (struct unionfs_mount *)malloc(sizeof(struct unionfs_mount), M_UNIONFSMNT, M_WAITOK | M_ZERO); /* * Save reference */ if (below) { VOP_UNLOCK(upperrootvp, 0); vn_lock(lowerrootvp, LK_EXCLUSIVE | LK_RETRY); ump->um_lowervp = upperrootvp; ump->um_uppervp = lowerrootvp; } else { ump->um_lowervp = lowerrootvp; ump->um_uppervp = upperrootvp; } ump->um_rootvp = NULLVP; ump->um_uid = uid; ump->um_gid = gid; ump->um_udir = udir; ump->um_ufile = ufile; ump->um_copymode = copymode; ump->um_whitemode = whitemode; MNT_ILOCK(mp); if ((lowerrootvp->v_mount->mnt_kern_flag & MNTK_MPSAFE) && (upperrootvp->v_mount->mnt_kern_flag & MNTK_MPSAFE)) mp->mnt_kern_flag |= MNTK_MPSAFE; MNT_IUNLOCK(mp); mp->mnt_data = ump; /* * Copy upper layer's RDONLY flag. */ mp->mnt_flag |= ump->um_uppervp->v_mount->mnt_flag & MNT_RDONLY; /* * Check whiteout */ if ((mp->mnt_flag & MNT_RDONLY) == 0) { memset(&fakecn, 0, sizeof(fakecn)); fakecn.cn_nameiop = LOOKUP; fakecn.cn_thread = td; error = VOP_WHITEOUT(ump->um_uppervp, &fakecn, LOOKUP); if (error) { if (below) { VOP_UNLOCK(ump->um_uppervp, 0); vrele(upperrootvp); } else vput(ump->um_uppervp); free(ump, M_UNIONFSMNT); mp->mnt_data = NULL; return (error); } } /* * Unlock the node */ VOP_UNLOCK(ump->um_uppervp, 0); /* * Get the unionfs root vnode. */ error = unionfs_nodeget(mp, ump->um_uppervp, ump->um_lowervp, NULLVP, &(ump->um_rootvp), NULL, td); vrele(upperrootvp); if (error) { free(ump, M_UNIONFSMNT); mp->mnt_data = NULL; return (error); } /* * Check mnt_flag */ if ((ump->um_lowervp->v_mount->mnt_flag & MNT_LOCAL) && (ump->um_uppervp->v_mount->mnt_flag & MNT_LOCAL)) mp->mnt_flag |= MNT_LOCAL; /* * Get new fsid */ vfs_getnewfsid(mp); len = MNAMELEN - 1; tmp = mp->mnt_stat.f_mntfromname; copystr((below ? "<below>:" : "<above>:"), tmp, len, &done); len -= done - 1; tmp += done - 1; copystr(target, tmp, len, NULL); UNIONFSDEBUG("unionfs_mount: from %s, on %s\n", mp->mnt_stat.f_mntfromname, mp->mnt_stat.f_mntonname); return (0); }
/*-----------------------------------------------------------------------------------*/ static char * ipaddrconf(char *str) { return copystr(ipaddr, str, sizeof(ipaddr)); }
static struct parseNode *getParseTreeVar(struct parserState *ps) { struct parseNode *result=NULL,*next,*ptr; int y; char *name; if(ps->token[0]=='}' || ps->token[0]==0) return NULL; name=copystr(ps->token); result=newNode(9); result->lineno=ps->lineno; next=newNode(0); next->lineno=ps->lineno; next->dat.s=name; result->dat.n=next; ptr=next; y=getToken(ps); if(y!=NameToken && ps->token[0]!='(') { state=y; error("Error! Method or variable name expected at %d, found %s\n" ,ps->lineno,ps->token); return result; } if(y==NameToken) { result->type=7; name=copystr(ps->token); next=newNode(0); next->lineno=ps->lineno; next->dat.s=name; ptr->next=next; ptr=next; y=getToken(ps); } if(ps->token[0]=='(') { ptr->next=getParseTreeMethod(ps); } else { result->type=5; while(ps->token[0]==',') { y=getToken(ps); if(y!=NameToken) { error("Error! Variable name expected at %d, found %s\n" ,ps->lineno,ps->token); return result; } name=copystr(ps->token); next=newNode(0); next->lineno=ps->lineno; next->dat.s=name; ptr->next=next; ptr=next; y=getToken(ps); } if(ps->token[0]!=';') { error("Error! Semicolon ; expected at %d\n",ps->lineno); return result; } y=getToken(ps); state=y; } return result; }
/*-----------------------------------------------------------------------------------*/ static char * netmaskconf(char *str) { return copystr(netmask, str, sizeof(netmask)); }
LIST * var_expand( LIST *l, char *in, char *end, LOL *lol, int cancopyin ) { char out_buf[ MAXSYM ]; string buf[1]; string out1[1]; /* Temporary buffer */ size_t prefix_length; char *out; char *inp = in; char *ov; /* for temp copy of variable in outbuf */ int depth; if( DEBUG_VAREXP ) printf( "expand '%.*s'\n", end - in, in ); /* This gets alot of cases: $(<) and $(>) */ if( in[0] == '$' && in[1] == '(' && in[3] == ')' && !in[4] ) { switch( in[2] ) { case '1': case '<': return list_copy( l, lol_get( lol, 0 ) ); case '2': case '>': return list_copy( l, lol_get( lol, 1 ) ); } } /* Just try simple copy of in to out. */ while( in < end ) if( *in++ == '$' && *in == '(' ) goto expand; /* No variables expanded - just add copy of input string to list. */ /* Cancopyin is an optimization: if the input was already a list */ /* item, we can use the copystr() to put it on the new list. */ /* Otherwise, we use the slower newstr(). */ if( cancopyin ) { return list_new( l, copystr( inp ) ); } else { LIST* r; string_new( buf ); string_append_range( buf, inp, end ); r = list_new( l, newstr( buf->value) ); string_free( buf ); return r; } expand: string_new( buf ); string_append_range( buf, inp, in - 1); /* copy the part before '$'. */ /* * Input so far (ignore blanks): * * stuff-in-outbuf $(variable) remainder * ^ ^ * in end * Output so far: * * stuff-in-outbuf $ * ^ ^ * out_buf out * * * We just copied the $ of $(...), so back up one on the output. * We now find the matching close paren, copying the variable and * modifiers between the $( and ) temporarily into out_buf, so that * we can replace :'s with MAGIC_COLON. This is necessary to avoid * being confused by modifier values that are variables containing * :'s. Ugly. */ depth = 1; inp = ++in; /* skip over the '(' */ while( in < end && depth ) { switch( *in++ ) { case '(': depth++; break; case ')': depth--; break; } } /* * Input so far (ignore blanks): * * stuff-in-outbuf $(variable) remainder * ^ ^ ^ * inp in end */ prefix_length = buf->size; string_append_range( buf, inp, in - 1 ); out = buf->value + prefix_length; for ( ov = out; ov < buf->value + buf->size; ++ov ) { switch( *ov ) { case ':': *ov = MAGIC_COLON; break; case '[': *ov = MAGIC_LEFT; break; case ']': *ov = MAGIC_RIGHT; break; } } /* * Input so far (ignore blanks): * * stuff-in-outbuf $(variable) remainder * ^ ^ * in end * Output so far: * * stuff-in-outbuf variable * ^ ^ ^ * out_buf out ov * * Later we will overwrite 'variable' in out_buf, but we'll be * done with it by then. 'variable' may be a multi-element list, * so may each value for '$(variable element)', and so may 'remainder'. * Thus we produce a product of three lists. */ { LIST *variables = 0; LIST *remainder = 0; LIST *vars; /* Recursively expand variable name & rest of input */ if( out < ov ) variables = var_expand( L0, out, ov, lol, 0 ); if( in < end ) remainder = var_expand( L0, in, end, lol, 0 ); /* Now produce the result chain */ /* For each variable name */ for( vars = variables; vars; vars = list_next( vars ) ) { LIST *value, *evalue = 0; char *colon; char *bracket; string variable[1]; char *varname; int sub1 = 0, sub2 = -1; VAR_EDITS edits; /* Look for a : modifier in the variable name */ /* Must copy into varname so we can modify it */ string_copy( variable, vars->string ); varname = variable->value; if( colon = strchr( varname, MAGIC_COLON ) ) { string_truncate( variable, colon - varname ); var_edit_parse( colon + 1, &edits ); } /* Look for [x-y] subscripting */ /* sub1 and sub2 are x and y. */ if ( bracket = strchr( varname, MAGIC_LEFT ) ) { /* ** Make all syntax errors in [] subscripting ** result in the same behavior: silenty return an empty ** expansion (by setting sub2 = 0). Brute force parsing; ** May get moved into yacc someday. */ char *s = bracket + 1; string_truncate( variable, bracket - varname ); do /* so we can use "break" */ { /* Allow negative indexes. */ if (! isdigit( *s ) && ! ( *s == '-') ) { sub2 = 0; break; } sub1 = atoi(s); /* Skip over the first symbol, which is either a digit or dash. */ s++; while ( isdigit( *s ) ) s++; if ( *s == MAGIC_RIGHT ) { sub2 = sub1; break; } if ( *s != '-') { sub2 = 0; break; } s++; if ( *s == MAGIC_RIGHT ) { sub2 = -1; break; } if (! isdigit( *s ) && ! ( *s == '-') ) { sub2 = 0; break; } /* First, compute the index of the last element. */ sub2 = atoi(s); s++; while ( isdigit( *s ) ) s++; if ( *s != MAGIC_RIGHT) sub2 = 0; } while (0); /* ** Anything but the end of the string, or the colon ** introducing a modifier is a syntax error. */ s++; if (*s && *s != MAGIC_COLON) sub2 = 0; *bracket = '\0'; } /* Get variable value, specially handling $(<), $(>), $(n) */ if( varname[0] == '<' && !varname[1] ) value = lol_get( lol, 0 ); else if( varname[0] == '>' && !varname[1] ) value = lol_get( lol, 1 ); else if( varname[0] >= '1' && varname[0] <= '9' && !varname[1] ) value = lol_get( lol, varname[0] - '1' ); else value = var_get( varname ); /* Handle negitive indexes: part two. */ { int length = list_length( value ); if (sub1 < 0) sub1 = length + sub1; else sub1 -= 1; if (sub2 < 0) sub2 = length + 1 + sub2 - sub1; else sub2 -= sub1; /* ** The "sub2 < 0" test handles the semantic error ** of sub2 < sub1. */ if ( sub2 < 0 ) sub2 = 0; } /* The fast path: $(x) - just copy the variable value. */ /* This is only an optimization */ if( out == out_buf && !bracket && !colon && in == end ) { string_free( variable ); l = list_copy( l, value ); continue; } /* Handle start subscript */ while( sub1 > 0 && value ) --sub1, value = list_next( value ); /* Empty w/ :E=default? */ if( !value && colon && edits.empty.ptr ) evalue = value = list_new( L0, newstr( edits.empty.ptr ) ); /* For each variable value */ string_new( out1 ); for( ; value; value = list_next( value ) ) { LIST *rem; size_t postfix_start; /* Handle end subscript (length actually) */ if( sub2 >= 0 && --sub2 < 0 ) break; string_truncate( buf, prefix_length ); /* Apply : mods, if present */ if( colon && edits.filemods ) var_edit_file( value->string, out1, &edits ); else string_append( out1, value->string ); if( colon && ( edits.upshift || edits.downshift || edits.to_slashes || edits.to_windows ) ) var_edit_shift( out1, &edits ); /* Handle :J=joinval */ /* If we have more values for this var, just */ /* keep appending them (with the join value) */ /* rather than creating separate LIST elements. */ if( colon && edits.join.ptr && ( list_next( value ) || list_next( vars ) ) ) { string_append( out1, edits.join.ptr ); continue; } string_append( buf, out1->value ); string_free( out1 ); string_new( out1 ); /* If no remainder, append result to output chain. */ if( in == end ) { l = list_new( l, newstr( buf->value ) ); continue; } /* For each remainder, append the complete string */ /* to the output chain. */ /* Remember the end of the variable expansion so */ /* we can just tack on each instance of 'remainder' */ postfix_start = buf->size; for( rem = remainder; rem; rem = list_next( rem ) ) { string_truncate( buf, postfix_start ); string_append( buf, rem->string ); l = list_new( l, newstr( buf->value ) ); } } string_free( out1 ); /* Toss used empty */ if( evalue ) list_free( evalue ); string_free( variable ); } /* variables & remainder were gifts from var_expand */ /* and must be freed */ if( variables ) list_free( variables ); if( remainder) list_free( remainder ); if( DEBUG_VAREXP ) { printf( "expanded to " ); list_print( l ); printf( "\n" ); } string_free( buf ); return l; } }
/*-----------------------------------------------------------------------------------*/ static char * drconf(char *str) { return copystr(gateway, str, sizeof(gateway)); }
static int ufs_extattr_lookup(struct vnode *start_dvp, int lockparent, char *dirname, struct vnode **vp, struct proc *p) { struct vop_lookup_args vargs; struct componentname cnp; struct vnode *target_vp; int error; bzero(&cnp, sizeof(cnp)); cnp.cn_nameiop = LOOKUP; cnp.cn_flags = ISLASTCN; if (lockparent == UE_GETDIR_LOCKPARENT) cnp.cn_flags |= LOCKPARENT; cnp.cn_proc = p; cnp.cn_cred = p->p_ucred; MALLOC(cnp.cn_pnbuf, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); cnp.cn_nameptr = cnp.cn_pnbuf; error = copystr(dirname, cnp.cn_pnbuf, MAXPATHLEN, (size_t *) &cnp.cn_namelen); if (error) { if (lockparent == UE_GETDIR_LOCKPARENT_DONT) { VOP_UNLOCK(start_dvp, 0, p); } FREE(cnp.cn_pnbuf, M_NAMEI); printf("ufs_extattr_lookup: copystr failed\n"); return (error); } cnp.cn_namelen--; /* trim nul termination */ vargs.a_desc = NULL; vargs.a_dvp = start_dvp; vargs.a_vpp = &target_vp; vargs.a_cnp = &cnp; error = ufs_lookup(&vargs); FREE(cnp.cn_pnbuf, M_NAMEI); if (error) { /* * Error condition, may have to release the lock on the parent * if ufs_lookup() didn't. */ if(lockparent == UE_GETDIR_LOCKPARENT_DONT) VOP_UNLOCK(start_dvp, 0, p); #if 0 /* -XXX does OpenBSD ufs_lookup always unlock on error? */ /* * Check that ufs_lookup() didn't release the lock when we * didn't want it to. */ if ((cnp.cn_flags & PDIRUNLOCK) && (lockparent == UE_GETDIR_LOCKPARENT)) panic("ufs_extattr_lookup: lockparent but PDIRUNLOCK"); #endif return (error); } /* if (target_vp == start_dvp) panic("ufs_extattr_lookup: target_vp == start_dvp"); */ #if 0 /* PDIRUNLOCK does not exist on OpenBSD */ if (target_vp != start_dvp && !(cnp.cn_flags & PDIRUNLOCK) && (lockparent == UE_GETDIR_LOCKPARENT_DONT)) panic("ufs_extattr_lookup: !lockparent but !PDIRUNLOCK"); if ((cnp.cn_flags & PDIRUNLOCK) && (lockparent == UE_GETDIR_LOCKPARENT)) panic("ufs_extattr_lookup: lockparent but PDIRUNLOCK"); #endif /* printf("ufs_extattr_lookup: success\n"); */ *vp = target_vp; return (0); }
/*-----------------------------------------------------------------------------------*/ static char * dnsconf(char *str) { return copystr(dnsserver, str, sizeof(dnsserver)); }
/* * Convert a pathname into a pointer to a vnode. * * The FOLLOW flag is set when symbolic links are to be followed * when they occur at the end of the name translation process. * Symbolic links are always followed for all other pathname * components other than the last. * * If the LOCKLEAF flag is set, a locked vnode is returned. * * The segflg defines whether the name is to be copied from user * space or kernel space. * * Overall outline of namei: * * copy in name * get starting directory * while (!done && !error) { * call lookup to search path. * if symbolic link, massage name in buffer and continue * } */ int namei(struct nameidata *ndp) { struct filedesc *fdp; /* pointer to file descriptor state */ char *cp; /* pointer into pathname argument */ struct vnode *dp; /* the directory we are searching */ struct iovec aiov; /* uio for reading symbolic links */ struct uio auio; int error, linklen; struct componentname *cnp = &ndp->ni_cnd; struct proc *p = cnp->cn_proc; ndp->ni_cnd.cn_cred = ndp->ni_cnd.cn_proc->p_ucred; #ifdef DIAGNOSTIC if (!cnp->cn_cred || !cnp->cn_proc) panic ("namei: bad cred/proc"); if (cnp->cn_nameiop & (~OPMASK)) panic ("namei: nameiop contaminated with flags"); if (cnp->cn_flags & OPMASK) panic ("namei: flags contaminated with nameiops"); #endif fdp = cnp->cn_proc->p_fd; /* * Get a buffer for the name to be translated, and copy the * name into the buffer. */ if ((cnp->cn_flags & HASBUF) == 0) cnp->cn_pnbuf = pool_get(&namei_pool, PR_WAITOK); if (ndp->ni_segflg == UIO_SYSSPACE) error = copystr(ndp->ni_dirp, cnp->cn_pnbuf, MAXPATHLEN, &ndp->ni_pathlen); else error = copyinstr(ndp->ni_dirp, cnp->cn_pnbuf, MAXPATHLEN, &ndp->ni_pathlen); /* * Fail on null pathnames */ if (error == 0 && ndp->ni_pathlen == 1) error = ENOENT; if (error) { pool_put(&namei_pool, cnp->cn_pnbuf); ndp->ni_vp = NULL; return (error); } #ifdef KTRACE if (KTRPOINT(cnp->cn_proc, KTR_NAMEI)) ktrnamei(cnp->cn_proc, cnp->cn_pnbuf); #endif #if NSYSTRACE > 0 if (ISSET(cnp->cn_proc->p_flag, P_SYSTRACE)) systrace_namei(ndp); #endif /* * Strip trailing slashes, as requested */ if (cnp->cn_flags & STRIPSLASHES) { char *end = cnp->cn_pnbuf + ndp->ni_pathlen - 2; cp = end; while (cp >= cnp->cn_pnbuf && (*cp == '/')) cp--; /* Still some remaining characters in the buffer */ if (cp >= cnp->cn_pnbuf) { ndp->ni_pathlen -= (end - cp); *(cp + 1) = '\0'; } } ndp->ni_loopcnt = 0; /* * Get starting point for the translation. */ if ((ndp->ni_rootdir = fdp->fd_rdir) == NULL) ndp->ni_rootdir = rootvnode; /* * Check if starting from root directory or current directory. */ if (cnp->cn_pnbuf[0] == '/') { dp = ndp->ni_rootdir; VREF(dp); } else { dp = fdp->fd_cdir; VREF(dp); } for (;;) { if (!dp->v_mount) { /* Give up if the directory is no longer mounted */ pool_put(&namei_pool, cnp->cn_pnbuf); return (ENOENT); } cnp->cn_nameptr = cnp->cn_pnbuf; ndp->ni_startdir = dp; if ((error = lookup(ndp)) != 0) { pool_put(&namei_pool, cnp->cn_pnbuf); return (error); } /* * Check for symbolic link */ if ((cnp->cn_flags & ISSYMLINK) == 0) { if ((cnp->cn_flags & (SAVENAME | SAVESTART)) == 0) pool_put(&namei_pool, cnp->cn_pnbuf); else cnp->cn_flags |= HASBUF; return (0); } if ((cnp->cn_flags & LOCKPARENT) && (cnp->cn_flags & ISLASTCN)) VOP_UNLOCK(ndp->ni_dvp, 0, p); if (ndp->ni_loopcnt++ >= MAXSYMLINKS) { error = ELOOP; break; } if (ndp->ni_pathlen > 1) cp = pool_get(&namei_pool, PR_WAITOK); else cp = cnp->cn_pnbuf; aiov.iov_base = cp; aiov.iov_len = MAXPATHLEN; auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_offset = 0; auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_SYSSPACE; auio.uio_procp = cnp->cn_proc; auio.uio_resid = MAXPATHLEN; error = VOP_READLINK(ndp->ni_vp, &auio, cnp->cn_cred); if (error) { badlink: if (ndp->ni_pathlen > 1) pool_put(&namei_pool, cp); break; } linklen = MAXPATHLEN - auio.uio_resid; if (linklen + ndp->ni_pathlen >= MAXPATHLEN) { error = ENAMETOOLONG; goto badlink; } if (ndp->ni_pathlen > 1) { bcopy(ndp->ni_next, cp + linklen, ndp->ni_pathlen); pool_put(&namei_pool, cnp->cn_pnbuf); cnp->cn_pnbuf = cp; } else cnp->cn_pnbuf[linklen] = '\0'; ndp->ni_pathlen += linklen; vput(ndp->ni_vp); dp = ndp->ni_dvp; /* * Check if root directory should replace current directory. */ if (cnp->cn_pnbuf[0] == '/') { vrele(dp); dp = ndp->ni_rootdir; VREF(dp); } } pool_put(&namei_pool, cnp->cn_pnbuf); vrele(ndp->ni_dvp); vput(ndp->ni_vp); ndp->ni_vp = NULL; return (error); }
static void processfile(const char *name, int failsilent, int warnonmissing, int printrevisioninfo, int *max_build, int *accum_build, int *max_year, int *max_month, int *max_day, int *ismodified) { char str[MAX_LINELENGTH], str_base[MAX_LINELENGTH]; char name_base[MAX_LINELENGTH]; char *p1; FILE *fp, *fp_base; int build, maj_build; int year, month, day; int cnt; char modchar; char *target; #ifdef DOWNSHIFT_PATHS string path; char *p; #endif target = copystr( (char*) name ); #ifdef DOWNSHIFT_PATHS string_copy( &path, target ); p = path.value; do { *p = tolower( *p ); #ifdef NT /* On NT, we must use backslashes or the file will not be found. */ if ( *p == '/' ) *p = PATH_DELIM; #endif } while ( *p++ ); target = path.value; #endif /* #ifdef DOWNSHIFT_PATHS */ /* since we also want to verify whether the file is modified in version * control, get the path to the working copy name * for every source file "<path>\<filename>, the "working copy" base can * be found in "<path>\.svn\text-base\<filename>.svn-base" */ if ((p1 = strrchr(name, PATH_DELIM)) != NULL) { ++p1; /* skip directory separator character ('\' in Windows, '/' in Linux) */ strncpy(name_base, name, (int)(p1 - name)); name_base[(int)(p1 - name)] = '\0'; } else { name_base[0] = '\0'; p1 = (char*)name; } /* if */ sprintf(name_base + strlen(name_base), ".svn%ctext-base%c%s.svn-base", PATH_DELIM, PATH_DELIM, p1); /* first extract the revision keywords */ fp = fopen(name, "r"); if (fp == NULL) { if (!failsilent) fprintf(stderr, "Failed to open input file '%s'\n", name); return; } /* if */ fp_base = fopen(name_base, "r"); /* fail silently */ build = 0; maj_build = 0; /* RCS / CVS */ year = month = day = 0; while (fgets(str, sizeof str, fp) != NULL) { if (fp_base == NULL || fgets(str_base, sizeof str_base, fp_base) == NULL) str_base[0] = '\0'; if ((p1 = strstr(str, "$Id:")) != NULL && strchr(p1+1, '$') != NULL) { if (sscanf(p1, "$Id: %*s %d %d-%d-%d", &build, &year, &month, &day) < 4 && sscanf(p1, "$Id: %*s %d %d/%d/%d", &build, &year, &month, &day) < 4) if (sscanf(p1, "$Id: %*s %d.%d %d-%d-%d", &maj_build, &build, &year, &month, &day) < 5) sscanf(p1, "$Id: %*s %d.%d %d/%d/%d", &maj_build, &build, &year, &month, &day); } else if ((p1 = strstr(str, "$Rev:")) != NULL && strchr(p1+1, '$') != NULL) { if (sscanf(p1, "$Rev: %d.%d", &maj_build, &build) < 2) { sscanf(p1, "$Rev: %d", &build); maj_build = 0; } /* if */ } else if ((p1 = strstr(str, "$Revision:")) != NULL && strchr(p1+1, '$') != NULL) { if (sscanf(p1, "$Revision: %d.%d", &maj_build, &build) < 2) { /* SvnRev also writes this keyword in its own generated file; read it * back for partial updates */ cnt = sscanf(p1, "$Revision: %d%c", &build, &modchar); if (cnt == 2 && modchar == 'M' && ismodified != NULL) *ismodified = 1; maj_build = 0; } /* if */ } else if ((p1 = strstr(str, "$Date:")) != NULL && strchr(p1+1, '$') != NULL) { if (sscanf(p1, "$Date: %d-%d-%d", &year, &month, &day) < 3) sscanf(p1, "$Date: %d/%d/%d", &year, &month, &day); } else if (ismodified != NULL && *ismodified == 0 && fp_base != NULL) { /* no keyword present, compare the lines for equivalence */ *ismodified = strcmp(str, str_base) != 0; } /* if */ if (maj_build) *accum_build += build; /* RCS / CVS */ else if (build > *max_build) *max_build = build; /* Subversion */ if (year > *max_year || (year == *max_year && month > *max_month) || (year == *max_year && month == *max_month && day > *max_day)) { *max_year = year; *max_month = month; *max_day = day; } /* if */ if (build > 0 && year > 0 && (fp_base == NULL || ismodified == NULL || *ismodified != 0)) break; /* both build # and date found, not comparing or modification * already found => no need to search further */ } /* while */ fclose(fp); if (fp_base != NULL) fclose(fp_base); if (build == 0 && warnonmissing) fprintf(stderr, "Missing revision info in: %s\n", name); else if (printrevisioninfo) printf("%d %4d-%02d-%02d %d %s\n", build, year, month, day, *ismodified, name); }
static int ufs_extattr_lookup(struct vnode *start_dvp, int lockparent, char *dirname, struct vnode **vp, struct thread *td) { struct vop_cachedlookup_args vargs; struct componentname cnp; struct vnode *target_vp; int error; bzero(&cnp, sizeof(cnp)); cnp.cn_nameiop = LOOKUP; cnp.cn_flags = ISLASTCN; if (lockparent == UE_GETDIR_LOCKPARENT) cnp.cn_flags |= LOCKPARENT; cnp.cn_lkflags = LK_EXCLUSIVE; cnp.cn_thread = td; cnp.cn_cred = td->td_ucred; cnp.cn_pnbuf = uma_zalloc(namei_zone, M_WAITOK); cnp.cn_nameptr = cnp.cn_pnbuf; error = copystr(dirname, cnp.cn_pnbuf, MAXPATHLEN, (size_t *) &cnp.cn_namelen); if (error) { if (lockparent == UE_GETDIR_LOCKPARENT_DONT) { VOP_UNLOCK(start_dvp, 0); } uma_zfree(namei_zone, cnp.cn_pnbuf); printf("ufs_extattr_lookup: copystr failed\n"); return (error); } cnp.cn_namelen--; /* trim nul termination */ vargs.a_gen.a_desc = NULL; vargs.a_dvp = start_dvp; vargs.a_vpp = &target_vp; vargs.a_cnp = &cnp; error = ufs_lookup(&vargs); uma_zfree(namei_zone, cnp.cn_pnbuf); if (error) { /* * Error condition, may have to release the lock on the parent * if ufs_lookup() didn't. */ if (lockparent == UE_GETDIR_LOCKPARENT_DONT) VOP_UNLOCK(start_dvp, 0); /* * Check that ufs_lookup() didn't release the lock when we * didn't want it to. */ if (lockparent == UE_GETDIR_LOCKPARENT) ASSERT_VOP_LOCKED(start_dvp, "ufs_extattr_lookup"); return (error); } /* if (target_vp == start_dvp) panic("ufs_extattr_lookup: target_vp == start_dvp"); */ if (target_vp != start_dvp && lockparent == UE_GETDIR_LOCKPARENT_DONT) VOP_UNLOCK(start_dvp, 0); if (lockparent == UE_GETDIR_LOCKPARENT) ASSERT_VOP_LOCKED(start_dvp, "ufs_extattr_lookup"); /* printf("ufs_extattr_lookup: success\n"); */ *vp = target_vp; return (0); }
void initializeTypeArray() { int i; dwarf_entry * cur_entry; struct genhashtable * ght=genallocatehashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings); struct genhashtable * sht=NULL; if (rootfile!=NULL) { char buf[512]; char a; int fd=open(rootfile,O_RDONLY); int offset=0; sht=genallocatehashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings); while(1) { if (read(fd,&a,1)>0) { if (a!=13&&a!=10) buf[offset++]=a; } else break; if (offset>0&&(a==13||a==10)) { buf[offset++]=0; { char *str=copystr(buf); genputtable(sht,str,str); } offset=0; } } } if (arrayfile!=NULL) { char buf[512]; char sizebuf[512]; char a; int fd=open(arrayfile,O_RDONLY); int offset=0; int readmore=1; int state=0; arrayt=genallocatehashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings); arraytype=genallocatehashtable((unsigned int (*)(void *)) & hashstring,(int (*)(void *,void *)) &equivalentstrings); while(readmore) { if (read(fd,&a,1)<=0) readmore=0; if (readmore) { if (a==' ') { state=1; buf[offset]=0; offset=0; } else if (a!=13&&a!=10) { if (state==0) buf[offset++]=a; else sizebuf[offset++]=a; } } if ((state==1)&&offset>0&&(a==13||a==10||!readmore)) { state=0; sizebuf[offset]=0; { char *str=copystr(buf); char *sizestr=copystr(sizebuf); genputtable(arrayt,str,sizestr); } offset=0; } } } /* Assign names */ for (i = 0; i < dwarf_entry_array_size; i++) { cur_entry = &dwarf_entry_array[i]; if (entry_is_type(cur_entry)) { collection_type* collection_ptr = (collection_type*)(cur_entry->entry_ptr); int j=0; int offset=0; int value=0; for(j=0;j<collection_ptr->num_members;j++) { dwarf_entry *entry=collection_ptr->members[j]; if (entry->tag_name==DW_TAG_inheritance) { value++; } else { member * member_ptr=(member *)entry->entry_ptr; char *name=member_ptr->name; dwarf_entry *type=member_ptr->type_ptr; char *typestr=printname(type,GETTYPE); char *poststr=printname(type,POSTNAME); if (typestr!=NULL) value++; } } } } for (i = 0; i < dwarf_entry_array_size; i++) { cur_entry = &dwarf_entry_array[i]; if (entry_is_type(cur_entry)) { collection_type* collection_ptr = (collection_type*)(cur_entry->entry_ptr); int j=0; int offset=0; int value=0; for(j=0;j<collection_ptr->num_members;j++) { dwarf_entry *entry=collection_ptr->members[j]; if (entry->tag_name==DW_TAG_inheritance) { value++; } else { member * member_ptr=(member *)entry->entry_ptr; char *name=member_ptr->name; dwarf_entry *type=member_ptr->type_ptr; char *typestr=printname(type,GETTYPE); char *poststr=printname(type,POSTNAME); if (typestr!=NULL) value++; } } if (collection_ptr->name!=NULL) { struct valuepair *vp=NULL; if (gencontains(ght,collection_ptr->name)) vp=(struct valuepair *)gengettable(ght,collection_ptr->name); if (vp==NULL||vp->value<value) { if (vp==NULL) { vp=(struct valuepair*)calloc(1,sizeof(struct valuepair)); genputtable(ght,collection_ptr->name,vp); } vp->value=value; vp->index=i; } } } } assigntype=1; if (sht!=NULL) { int repeat=1; while(repeat) { repeat=0; for (i = 0; i < dwarf_entry_array_size; i++) { cur_entry = &dwarf_entry_array[i]; if (entry_is_type(cur_entry)) { collection_type* collection_ptr = (collection_type*)(cur_entry->entry_ptr); int j=0; int offset=0; int value=0; if (!gencontains(sht,collection_ptr->name)) continue; if (gencontains(ght,collection_ptr->name)) { struct valuepair *vp=(struct valuepair*)gengettable(ght,collection_ptr->name); if (vp->index!=i) continue; } for(j=0;j<collection_ptr->num_members;j++) { dwarf_entry *entry=collection_ptr->members[j]; if (entry->tag_name==DW_TAG_inheritance) { inherit *in_ptr=(inherit*)collection_ptr->members[j]->entry_ptr; dwarf_entry *typeptr=in_ptr->target_ptr; collection_type* sub_ptr = (collection_type*)(typeptr->entry_ptr); if (!gencontains(sht,sub_ptr->name)) { repeat=1; genputtable(sht,sub_ptr->name,sub_ptr->name); } } else { member * member_ptr=(member *)entry->entry_ptr; char *name=member_ptr->name; dwarf_entry *type=member_ptr->type_ptr; char *typestr=printname(type,GETJUSTTYPE); if (typestr!=NULL&&!gencontains(sht,typestr)) { repeat=1; genputtable(sht,typestr,typestr); } } } } } } } for (i = 0; i < dwarf_entry_array_size; i++) { cur_entry = &dwarf_entry_array[i]; if (entry_is_type(cur_entry)) { collection_type* collection_ptr = (collection_type*)(cur_entry->entry_ptr); int j=0; int offset=0; if (collection_ptr->name==NULL) continue; if (sht!=NULL&&!gencontains(sht,collection_ptr->name)) continue; if (gencontains(ght,collection_ptr->name)) { struct valuepair *vp=(struct valuepair*)gengettable(ght,collection_ptr->name); if (vp->index!=i) continue; } j=0; printf("structure %s ",collection_ptr->name); while(j<collection_ptr->num_members&& collection_ptr->members[j]->tag_name==DW_TAG_inheritance) { inherit *in_ptr=(inherit*)collection_ptr->members[j]->entry_ptr; dwarf_entry *typeptr=in_ptr->target_ptr; collection_type* sub_ptr = (collection_type*)(typeptr->entry_ptr); if (j==0) printf("subclass of "); else printf(", "); printf("%s ",sub_ptr->name); j++; } printf("{ \n"); for(j=0;j<collection_ptr->num_members;j++) { dwarf_entry *entry=collection_ptr->members[j]; if (entry->tag_name==DW_TAG_inheritance) { inherit * inherit_ptr=(inherit *)entry->entry_ptr; if (inherit_ptr->data_member_location>offset) { printf(" reserved byte[%ld];\n",inherit_ptr->data_member_location-offset); offset=inherit_ptr->data_member_location; } { dwarf_entry *type=inherit_ptr->target_ptr; collection_type *c_ptr=(collection_type*)type->entry_ptr; offset+=printtype(c_ptr,ght); } } else { member * member_ptr=(member *)entry->entry_ptr; char *name=member_ptr->name; dwarf_entry *type=member_ptr->type_ptr; char *typestr=printname(type,GETTYPE); char *poststr=printname(type,POSTNAME); char *newname=NULL; if (member_ptr->data_member_location>offset) { printf(" reserved byte[%ld];\n",member_ptr->data_member_location-offset); offset=member_ptr->data_member_location; } offset+=getsize(type); newname=escapestr(name); { char buf[512]; char *dtype; sprintf(buf, "%s.%s\0", collection_ptr->name,newname); if (arrayt!=NULL&&gencontains(arrayt, &buf)) { genputtable(arraytype, copystr(buf), typestr); dtype=deref(typestr); printf(" %s_array * %s%s;\n",dtype,newname,poststr); free(dtype); } else printf(" %s %s%s;\n",typestr,newname,poststr); } free(newname); } } if (offset<collection_ptr->byte_size) printf(" reserved byte[%ld];\n",collection_ptr->byte_size-offset); printf("}\n\n"); } } if (arrayt!=NULL) { struct geniterator * gi=gengetiterator(arrayt); while(1) { char * str=(char *)gennext(gi); char *size=NULL; char *typestr=NULL; if (str==NULL) break; size=(char *)gengettable(arrayt,str); typestr=deref((char *)gengettable(arraytype,str)); printf("structure %s_array {\n",typestr); printf(" %s elem[%s];\n",typestr,size); printf("}\n"); free(typestr); } genfreeiterator(gi); } }
/* * filepath may be either a directory or a fully-qualified path. * if it's fully-qualified, only directory entries that sort alphabetically * after the specified file will be returned. * * morefiles will be set if there are more entries left in the directory * after maxentries have been returned. This is intended to let the caller * know they can continue reading. * * Note that the directory may change while we're reading it. If it does, * files that have been added or removed since we started reading it may * not be accurately reflected. */ int list_directory( ctx_t *c, /* ARGSUSED */ int maxentries, char *listDir, /* directory to list */ char *startFile, /* if continuing, start here */ char *restrictions, uint32_t *morefiles, /* OUT */ sqm_lst_t **direntries) /* OUT */ { int rval = 0; int st = 0; DIR *curdir; /* Variable for directory system calls */ dirent64_t *entry; /* Pointer to a directory entry */ dirent64_t *entryp; struct stat64 sout; restrict_t filter = {0}; char *data; /* Pointer to data item to add to list */ node_t *node; sqm_lst_t *lstp = NULL; char buf[MAXPATHLEN + 1]; char *fname; if (ISNULL(listDir, direntries, morefiles)) { return (-1); } *morefiles = 0; /* Set up wildcard restrictions */ rval = set_restrict(restrictions, &filter); if (rval) { return (rval); } curdir = opendir(listDir); /* Set up to ask for directory entries */ if (curdir == NULL) { return (samrerr(SE_NOSUCHPATH, listDir)); } *direntries = lst_create(); /* Return results in this list */ if (*direntries == NULL) { closedir(curdir); return (-1); /* If allocation failed, samerr is set */ } lstp = *direntries; entry = mallocer(sizeof (struct dirent64) + MAXPATHLEN + 1); if (entry == NULL) { closedir(curdir); lst_free(*direntries); *direntries = NULL; return (-1); } /* Walk through directory entries */ while ((rval = readdir64_r(curdir, entry, &entryp)) == 0) { if (entryp == NULL) { break; } fname = (char *)&(entry->d_name[0]); if ((strcmp(fname, ".") == 0) || (strcmp(fname, "..") == 0)) { continue; } /* * If we were given a non-directory, start after * that file alphabetically. */ if (startFile != NULL) { if ((strcmp(fname, startFile)) <= 0) { continue; } } /* Create full pathname and get stat info */ snprintf(buf, sizeof (buf), "%s/%s", listDir, fname); if (lstat64(buf, &sout) != 0) { continue; /* Ignore file which can't be stat'ed */ } /* * think about ways to avoid a double-stat in when we're * fetching file details */ if (check_restrict_stat(fname, &sout, &filter)) { continue; /* Not this entry */ } /* copy to allocated struct */ data = copystr(fname); if (data == NULL) { rval = -1; break; /* samerr already set */ } /* * caller wants all entries for the directory * should there be a top-end limit, to avoid the case where * the directory has millions of entries? */ if (maxentries <= 0) { rval = lst_append(lstp, data); if (rval != 0) { free(data); break; } continue; } /* * Directory may have more entries than requested, so pre-sort * the list so we return the first <n> sorted alphabetically. */ for (node = lstp->head; node != NULL; node = node->next) { st = strcmp(data, (char *)(node->data)); if (st > 0) { continue; } if (st < 0) { rval = lst_ins_before(lstp, node, data); data = NULL; } if ((rval != 0) || (st == 0)) { free(data); data = NULL; } break; } /* entry sorts higher than existing entries */ if (data != NULL) { if (lstp->length < maxentries) { rval = lst_append(lstp, data); if (rval != 0) { free(data); break; } } else { /* no room for this entry */ free(data); (*morefiles)++; } } /* Keep list to designated limits */ if (lstp->length > maxentries) { /* pop off the last entry */ lst_remove(lstp, lstp->tail); (*morefiles)++; } } closedir(curdir); free(entry); if (rval) { lst_free_deep(*direntries); *direntries = NULL; } else if (maxentries <= 0) { lst_qsort(*direntries, node_cmp); } return (rval); }
int getattributes(entry_t *entry, int argc, char **argv) /* Convert state or difference file info into file attributes. */ { int i; int attr; #define A_MODE1 0x01 /* Some of these attributes follow the name */ #define A_MODE 0x02 #define A_OWNER 0x04 #define A_SIZETIME 0x08 #define A_DEV 0x10 #define A_LINK 0x20 switch (argv[0][0]) { case 'd': /* Directory. */ entry->type= F_DIR; attr= A_MODE1 | A_OWNER; break; case 'b': /* Block device. */ entry->type= F_BLK; attr= A_MODE1 | A_OWNER | A_DEV; break; case 'c': /* Character device. */ entry->type= F_CHR; attr= A_MODE1 | A_OWNER | A_DEV; break; case 'p': /* Named pipe. */ entry->type= F_PIPE; attr= A_MODE1 | A_OWNER; break; case '-': /* Symlink. */ entry->type= F_LINK; attr= A_LINK; break; default: /* Normal file. */ entry->type= F_FILE; attr= A_MODE | A_OWNER | A_SIZETIME; } if (attr & (A_MODE | A_MODE1)) { entry->mode= strtoul(argv[0] + (attr & A_MODE1), nil, 010); } i= 1; if (attr & A_OWNER) { if (i + 2 > argc) return 0; entry->uid= strtoul(argv[i++], nil, 10); entry->gid= strtoul(argv[i++], nil, 10); } if (attr & A_SIZETIME) { if (i + 2 > argc) return 0; entry->size= strtoul(argv[i++], nil, 10); entry->mtime= strtoul(argv[i++], nil, 10); } if (attr & A_DEV) { if (i + 1 > argc) return 0; entry->rdev= strtoul(argv[i++], nil, 0x10); } if (attr & A_LINK) { if (i + 1 > argc) return 0; entry->link= argv[i++]; } entry->linked= entry->lastlink= 0; if (i < argc) { /* It has a fake inode number, so it is a hard link. */ static struct links { /* List of hard links. */ struct links *next; unsigned long fake_ino; char *path; } *links[1024]; struct links **plp, *lp; unsigned long fake_ino; fake_ino= strtoul(argv[i++], nil, 10); plp= &links[fake_ino % arraysize(links)]; while ((lp= *plp) != nil && lp->fake_ino != fake_ino) plp= &lp->next; if (lp == nil) { /* New link. */ *plp= lp= allocate(nil, sizeof(*lp)); lp->next= nil; lp->fake_ino= fake_ino; lp->path= copystr(entry->path); } else { /* Linked to. */ entry->link= lp->path; entry->linked= 1; } if (i < argc) { if (strcmp(argv[i++], "last") != 0) return 0; /* Last hard link of a file. */ forget(lp->path); *plp= lp->next; deallocate(lp); entry->lastlink= 1; } } if (i != argc) return 0; return 1; }