Example #1
0
static int
merge_dirs (const char *root, char **dirs, int n_dirs)
{
  DIR *dir;
  char *subdirs[n_dirs];
  struct dirent *dirent;
  struct stat st;
  char *src_path;
  char *dest_path;
  int conflict;
  int i, j;

  for (i = 0; i < n_dirs; i++)
    {
      if (dirs[i] == NULL)
        continue;

      dir = opendir (dirs[i]);
      if (dir == NULL)
        continue;

      while ((dirent = readdir (dir)) != NULL)
        {
          src_path = strconcat (dirs[i], "/", dirent->d_name);

          if (strcmp (dirent->d_name, ".") == 0 ||
              strcmp (dirent->d_name, "..") == 0)
            continue;

          dest_path = strconcat (root, "/", dirent->d_name);

          if (lstat (dest_path, &st) == 0)
            {
              free (dest_path);
              continue; /* We already copyed this file */
            }

          if (lstat (src_path, &st) < 0)
            {
              free (dest_path);
              continue;
            }

          if (S_ISCHR (st.st_mode) ||
              S_ISBLK (st.st_mode) ||
              S_ISFIFO (st.st_mode) ||
              S_ISSOCK (st.st_mode))
            {
              fprintf (stderr, "WARNING: ignoring special file %s\n", src_path);
              free (dest_path);
              continue;
            }

          conflict = has_conflict (dirs, n_dirs, dirent->d_name, i);

          if (conflict == NO_CONFLICTS)
            {
              bind_file (src_path, dest_path, &st);
            }
          else if (conflict == DIR_CONFLICT)
            {
              if (mkdir (dest_path, st.st_mode & 0777))
                fatal_errno ("create merged dir");

              if (lchown(dest_path, st.st_uid, st.st_gid) < 0)
                fatal_errno ("lchown");

              for (j = 0; j < n_dirs; j++)
                subdirs[j] = get_subdir (dirs[j], dirent->d_name);

              merge_dirs (dest_path, subdirs, n_dirs);
              for (j = 0; j < n_dirs; j++)
                {
                  if (subdirs[j])
                    free (subdirs[j]);
                }
            }
          else
            fatal ("Filename conflicts, refusing to mount\n");

          free (dest_path);
        }
    }

  return 0;
}
Example #2
0
/*****************************************************************************
 * Open: open the file
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    sout_access_out_t   *p_access = (sout_access_out_t*)p_this;
    int                 fd;

    config_ChainParse( p_access, SOUT_CFG_PREFIX, ppsz_sout_options, p_access->p_cfg );

    if( !p_access->psz_path )
    {
        msg_Err( p_access, "no file name specified" );
        return VLC_EGENERIC;
    }

    bool overwrite = var_GetBool (p_access, SOUT_CFG_PREFIX"overwrite");
    bool append = var_GetBool( p_access, SOUT_CFG_PREFIX "append" );

    if (!strcmp (p_access->psz_access, "fd"))
    {
        char *end;

        fd = strtol (p_access->psz_path, &end, 0);
        if (!*p_access->psz_path || *end)
        {
            msg_Err (p_access, "invalid file descriptor: %s",
                     p_access->psz_path);
            return VLC_EGENERIC;
        }
        fd = vlc_dup (fd);
        if (fd == -1)
        {
            msg_Err (p_access, "cannot use file descriptor: %s",
                     vlc_strerror_c(errno));
            return VLC_EGENERIC;
        }
    }
    else
    if( !strcmp( p_access->psz_path, "-" ) )
    {
#if defined( _WIN32 ) || defined( __OS2__ )
        setmode (STDOUT_FILENO, O_BINARY);
#endif
        fd = vlc_dup (STDOUT_FILENO);
        if (fd == -1)
        {
            msg_Err (p_access, "cannot use standard output: %s",
                     vlc_strerror_c(errno));
            return VLC_EGENERIC;
        }
        msg_Dbg( p_access, "using stdout" );
    }
    else
    {
        const char *path = p_access->psz_path;
        char *buf = NULL;

        if (var_InheritBool (p_access, SOUT_CFG_PREFIX"format"))
        {
            buf = str_format_time (path);
            path_sanitize (buf);
            path = buf;
        }

        int flags = O_RDWR | O_CREAT | O_LARGEFILE;
        if (!overwrite)
            flags |= O_EXCL;
        if (!append)
            flags |= O_TRUNC;
#ifdef O_SYNC
        if (var_GetBool (p_access, SOUT_CFG_PREFIX"sync"))
            flags |= O_SYNC;
#endif
        do
        {
            fd = vlc_open (path, flags, 0666);
            if (fd != -1)
                break;
            if (fd == -1)
                msg_Err (p_access, "cannot create %s: %s", path,
                         vlc_strerror_c(errno));
            if (overwrite || errno != EEXIST)
                break;
            flags &= ~O_EXCL;
        }
        while (dialog_Question (p_access, path,
                                _("The output file already exists. "
                                "If recording continues, the file will be "
                                "overridden and its content will be lost."),
                                _("Keep existing file"),
                                _("Overwrite"), NULL) == 2);
        free (buf);
        if (fd == -1)
            return VLC_EGENERIC;
    }

    struct stat st;

    if (fstat (fd, &st))
    {
        msg_Err (p_access, "write error: %s", vlc_strerror_c(errno));
        close (fd);
        return VLC_EGENERIC;
    }

    p_access->pf_read  = Read;

    if (S_ISREG(st.st_mode) || S_ISBLK(st.st_mode))
    {
        p_access->pf_write = Write;
        p_access->pf_seek  = Seek;
    }
#ifdef S_ISSOCK
    else if (S_ISSOCK(st.st_mode))
    {
        p_access->pf_write = Send;
        p_access->pf_seek = NoSeek;
    }
#endif
    else
    {
        p_access->pf_write = WritePipe;
        p_access->pf_seek = NoSeek;
    }
    p_access->pf_control = Control;
    p_access->p_sys    = (void *)(intptr_t)fd;

    msg_Dbg( p_access, "file access output opened (%s)", p_access->psz_path );
    if (append)
        lseek (fd, 0, SEEK_END);

    return VLC_SUCCESS;
}
Example #3
0
int fuse_valid_type(int m)
{
	return S_ISREG(m) || S_ISDIR(m) || S_ISLNK(m) || S_ISCHR(m) ||
		S_ISBLK(m) || S_ISFIFO(m) || S_ISSOCK(m);
}
static int ncp_fill_super(struct super_block *sb, void *raw_data, int silent)
{
	struct ncp_mount_data_kernel data;
	struct ncp_server *server;
	struct file *ncp_filp;
	struct inode *root_inode;
	struct inode *sock_inode;
	struct socket *sock;
	int error;
	int default_bufsize;
#ifdef CONFIG_NCPFS_PACKET_SIGNING
	int options;
#endif
	struct ncp_entry_info finfo;

	memset(&data, 0, sizeof(data));
	server = kzalloc(sizeof(struct ncp_server), GFP_KERNEL);
	if (!server)
		return -ENOMEM;
	sb->s_fs_info = server;

	error = -EFAULT;
	if (raw_data == NULL)
		goto out;
	switch (*(int*)raw_data) {
		case NCP_MOUNT_VERSION:
			{
				struct ncp_mount_data* md = (struct ncp_mount_data*)raw_data;

				data.flags = md->flags;
				data.int_flags = NCP_IMOUNT_LOGGEDIN_POSSIBLE;
				data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid);
				data.wdog_pid = find_get_pid(md->wdog_pid);
				data.ncp_fd = md->ncp_fd;
				data.time_out = md->time_out;
				data.retry_count = md->retry_count;
				data.uid = make_kuid(current_user_ns(), md->uid);
				data.gid = make_kgid(current_user_ns(), md->gid);
				data.file_mode = md->file_mode;
				data.dir_mode = md->dir_mode;
				data.info_fd = -1;
				memcpy(data.mounted_vol, md->mounted_vol,
					NCP_VOLNAME_LEN+1);
			}
			break;
		case NCP_MOUNT_VERSION_V4:
			{
				struct ncp_mount_data_v4* md = (struct ncp_mount_data_v4*)raw_data;

				data.flags = md->flags;
				data.mounted_uid = make_kuid(current_user_ns(), md->mounted_uid);
				data.wdog_pid = find_get_pid(md->wdog_pid);
				data.ncp_fd = md->ncp_fd;
				data.time_out = md->time_out;
				data.retry_count = md->retry_count;
				data.uid = make_kuid(current_user_ns(), md->uid);
				data.gid = make_kgid(current_user_ns(), md->gid);
				data.file_mode = md->file_mode;
				data.dir_mode = md->dir_mode;
				data.info_fd = -1;
			}
			break;
		default:
			error = -ECHRNG;
			if (memcmp(raw_data, "vers", 4) == 0) {
				error = ncp_parse_options(&data, raw_data);
			}
			if (error)
				goto out;
			break;
	}
	error = -EINVAL;
	if (!uid_valid(data.mounted_uid) || !uid_valid(data.uid) ||
	    !gid_valid(data.gid))
		goto out;
	error = -EBADF;
	ncp_filp = fget(data.ncp_fd);
	if (!ncp_filp)
		goto out;
	error = -ENOTSOCK;
	sock_inode = file_inode(ncp_filp);
	if (!S_ISSOCK(sock_inode->i_mode))
		goto out_fput;
	sock = SOCKET_I(sock_inode);
	if (!sock)
		goto out_fput;
		
	if (sock->type == SOCK_STREAM)
		default_bufsize = 0xF000;
	else
		default_bufsize = 1024;

	sb->s_flags |= MS_NODIRATIME;	/* probably even noatime */
	sb->s_maxbytes = 0xFFFFFFFFU;
	sb->s_blocksize = 1024;	/* Eh...  Is this correct? */
	sb->s_blocksize_bits = 10;
	sb->s_magic = NCP_SUPER_MAGIC;
	sb->s_op = &ncp_sops;
	sb->s_d_op = &ncp_dentry_operations;
	sb->s_bdi = &server->bdi;

	server = NCP_SBP(sb);
	memset(server, 0, sizeof(*server));

	error = bdi_setup_and_register(&server->bdi, "ncpfs", BDI_CAP_MAP_COPY);
	if (error)
		goto out_fput;

	server->ncp_filp = ncp_filp;
	server->ncp_sock = sock;
	
	if (data.info_fd != -1) {
		struct socket *info_sock;

		error = -EBADF;
		server->info_filp = fget(data.info_fd);
		if (!server->info_filp)
			goto out_bdi;
		error = -ENOTSOCK;
		sock_inode = file_inode(server->info_filp);
		if (!S_ISSOCK(sock_inode->i_mode))
			goto out_fput2;
		info_sock = SOCKET_I(sock_inode);
		if (!info_sock)
			goto out_fput2;
		error = -EBADFD;
		if (info_sock->type != SOCK_STREAM)
			goto out_fput2;
		server->info_sock = info_sock;
	}

/*	server->lock = 0;	*/
	mutex_init(&server->mutex);
	server->packet = NULL;
/*	server->buffer_size = 0;	*/
/*	server->conn_status = 0;	*/
/*	server->root_dentry = NULL;	*/
/*	server->root_setuped = 0;	*/
	mutex_init(&server->root_setup_lock);
#ifdef CONFIG_NCPFS_PACKET_SIGNING
/*	server->sign_wanted = 0;	*/
/*	server->sign_active = 0;	*/
#endif
	init_rwsem(&server->auth_rwsem);
	server->auth.auth_type = NCP_AUTH_NONE;
/*	server->auth.object_name_len = 0;	*/
/*	server->auth.object_name = NULL;	*/
/*	server->auth.object_type = 0;		*/
/*	server->priv.len = 0;			*/
/*	server->priv.data = NULL;		*/

	server->m = data;
	/* Although anything producing this is buggy, it happens
	   now because of PATH_MAX changes.. */
	if (server->m.time_out < 1) {
		server->m.time_out = 10;
		printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
	}
	server->m.time_out = server->m.time_out * HZ / 100;
	server->m.file_mode = (server->m.file_mode & S_IRWXUGO) | S_IFREG;
	server->m.dir_mode = (server->m.dir_mode & S_IRWXUGO) | S_IFDIR;

#ifdef CONFIG_NCPFS_NLS
	/* load the default NLS charsets */
	server->nls_vol = load_nls_default();
	server->nls_io = load_nls_default();
#endif /* CONFIG_NCPFS_NLS */

	atomic_set(&server->dentry_ttl, 0);	/* no caching */

	INIT_LIST_HEAD(&server->tx.requests);
	mutex_init(&server->rcv.creq_mutex);
	server->tx.creq		= NULL;
	server->rcv.creq	= NULL;

	init_timer(&server->timeout_tm);
#undef NCP_PACKET_SIZE
#define NCP_PACKET_SIZE 131072
	error = -ENOMEM;
	server->packet_size = NCP_PACKET_SIZE;
	server->packet = vmalloc(NCP_PACKET_SIZE);
	if (server->packet == NULL)
		goto out_nls;
	server->txbuf = vmalloc(NCP_PACKET_SIZE);
	if (server->txbuf == NULL)
		goto out_packet;
	server->rxbuf = vmalloc(NCP_PACKET_SIZE);
	if (server->rxbuf == NULL)
		goto out_txbuf;

	lock_sock(sock->sk);
	server->data_ready	= sock->sk->sk_data_ready;
	server->write_space	= sock->sk->sk_write_space;
	server->error_report	= sock->sk->sk_error_report;
	sock->sk->sk_user_data	= server;
	sock->sk->sk_data_ready	  = ncp_tcp_data_ready;
	sock->sk->sk_error_report = ncp_tcp_error_report;
	if (sock->type == SOCK_STREAM) {
		server->rcv.ptr = (unsigned char*)&server->rcv.buf;
		server->rcv.len = 10;
		server->rcv.state = 0;
		INIT_WORK(&server->rcv.tq, ncp_tcp_rcv_proc);
		INIT_WORK(&server->tx.tq, ncp_tcp_tx_proc);
		sock->sk->sk_write_space = ncp_tcp_write_space;
	} else {
		INIT_WORK(&server->rcv.tq, ncpdgram_rcv_proc);
		INIT_WORK(&server->timeout_tq, ncpdgram_timeout_proc);
		server->timeout_tm.data = (unsigned long)server;
		server->timeout_tm.function = ncpdgram_timeout_call;
	}
	release_sock(sock->sk);

	ncp_lock_server(server);
	error = ncp_connect(server);
	ncp_unlock_server(server);
	if (error < 0)
		goto out_rxbuf;
	DPRINTK("ncp_fill_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));

	error = -EMSGSIZE;	/* -EREMOTESIDEINCOMPATIBLE */
#ifdef CONFIG_NCPFS_PACKET_SIGNING
	if (ncp_negotiate_size_and_options(server, default_bufsize,
		NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
	{
		if (options != NCP_DEFAULT_OPTIONS)
		{
			if (ncp_negotiate_size_and_options(server, 
				default_bufsize,
				options & 2, 
				&(server->buffer_size), &options) != 0)
				
			{
				goto out_disconnect;
			}
		}
		ncp_lock_server(server);
		if (options & 2)
			server->sign_wanted = 1;
		ncp_unlock_server(server);
	}
	else 
#endif	/* CONFIG_NCPFS_PACKET_SIGNING */
	if (ncp_negotiate_buffersize(server, default_bufsize,
  				     &(server->buffer_size)) != 0)
		goto out_disconnect;
	DPRINTK("ncpfs: bufsize = %d\n", server->buffer_size);

	memset(&finfo, 0, sizeof(finfo));
	finfo.i.attributes	= aDIR;
	finfo.i.dataStreamSize	= 0;	/* ignored */
	finfo.i.dirEntNum	= 0;
	finfo.i.DosDirNum	= 0;
#ifdef CONFIG_NCPFS_SMALLDOS
	finfo.i.NSCreator	= NW_NS_DOS;
#endif
	finfo.volume		= NCP_NUMBER_OF_VOLUMES;
	/* set dates of mountpoint to Jan 1, 1986; 00:00 */
	finfo.i.creationTime	= finfo.i.modifyTime
				= cpu_to_le16(0x0000);
	finfo.i.creationDate	= finfo.i.modifyDate
				= finfo.i.lastAccessDate
				= cpu_to_le16(0x0C21);
	finfo.i.nameLen		= 0;
	finfo.i.entryName[0]	= '\0';

	finfo.opened		= 0;
	finfo.ino		= 2;	/* tradition */

	server->name_space[finfo.volume] = NW_NS_DOS;

	error = -ENOMEM;
        root_inode = ncp_iget(sb, &finfo);
        if (!root_inode)
		goto out_disconnect;
	DPRINTK("ncp_fill_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
	sb->s_root = d_make_root(root_inode);
        if (!sb->s_root)
		goto out_disconnect;
	return 0;

out_disconnect:
	ncp_lock_server(server);
	ncp_disconnect(server);
	ncp_unlock_server(server);
out_rxbuf:
	ncp_stop_tasks(server);
	vfree(server->rxbuf);
out_txbuf:
	vfree(server->txbuf);
out_packet:
	vfree(server->packet);
out_nls:
#ifdef CONFIG_NCPFS_NLS
	unload_nls(server->nls_io);
	unload_nls(server->nls_vol);
#endif
	mutex_destroy(&server->rcv.creq_mutex);
	mutex_destroy(&server->root_setup_lock);
	mutex_destroy(&server->mutex);
out_fput2:
	if (server->info_filp)
		fput(server->info_filp);
out_bdi:
	bdi_destroy(&server->bdi);
out_fput:
	/* 23/12/1998 Marcin Dalecki <*****@*****.**>:
	 * 
	 * The previously used put_filp(ncp_filp); was bogus, since
	 * it doesn't perform proper unlocking.
	 */
	fput(ncp_filp);
out:
	put_pid(data.wdog_pid);
	sb->s_fs_info = NULL;
	kfree(server);
	return error;
}
Example #5
0
asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3)
{
	struct file *filp;
	struct inode *ino;
	struct strbuf __user *ctlptr;
	struct strbuf __user *datptr;
	struct strbuf ctl, dat;
	int __user *flgptr;
	int flags;
	int error = -EBADF;
	struct fdtable *fdt;

	SOLD("entry");
	lock_kernel();
	if(fd >= NR_OPEN) goto out;

	fdt = files_fdtable(current->files);
	filp = fdt->fd[fd];
	if(!filp) goto out;

	ino = filp->f_dentry->d_inode;
	if (!ino || !S_ISSOCK(ino->i_mode))
		goto out;

	ctlptr = (struct strbuf __user *)A(arg1);
	datptr = (struct strbuf __user *)A(arg2);
	flgptr = (int __user *)A(arg3);

	error = -EFAULT;

	if (ctlptr) {
		if (copy_from_user(&ctl,ctlptr,sizeof(struct strbuf)) || 
		    put_user(-1,&ctlptr->len))
			goto out;
	} else
		ctl.maxlen = -1;

	if (datptr) {
		if (copy_from_user(&dat,datptr,sizeof(struct strbuf)) || 
		    put_user(-1,&datptr->len))
			goto out;
	} else
		dat.maxlen = -1;

	if (get_user(flags,flgptr))
		goto out;

	switch (flags) {
	case 0:
	case MSG_HIPRI:
	case MSG_ANY:
	case MSG_BAND:
		break;
	default:
		error = -EINVAL;
		goto out;
	}

	error = timod_getmsg(fd,A(ctl.buf),ctl.maxlen,&ctlptr->len,
				A(dat.buf),dat.maxlen,&datptr->len,&flags);

	if (!error && put_user(flags,flgptr))
		error = -EFAULT;
out:
	unlock_kernel();
	SOLD("done");
	return error;
}
Example #6
0
C_Int_t Posix_FileSys_ST_isSock (C_Mode_t m) {
  return S_ISSOCK(m);
}
Example #7
0
/*
 * Create the file, or the directory
 *
 *  fname is the original filename
 *  ofile is the output filename (may be in a different directory)
 *
 * Returns:  CF_SKIP     if file should be skipped
 *           CF_ERROR    on error
 *           CF_EXTRACT  file created and data to restore
 *           CF_CREATED  file created no data to restore
 *
 *   Note, we create the file here, except for special files,
 *     we do not set the attributes because we want to first
 *     write the file, then when the writing is done, set the
 *     attributes.
 *   So, we return with the file descriptor open for normal
 *     files.
 *
 */
int create_file(JCR *jcr, ATTR *attr, BFILE *bfd, int replace)
{
   mode_t new_mode, parent_mode;
   int flags;
   uid_t uid;
   gid_t gid;
   int pnl;
   bool exists = false;
   struct stat mstatp;

   bfd->reparse_point = false;
   if (is_win32_stream(attr->data_stream)) {
      set_win32_backup(bfd);
   } else {
      set_portable_backup(bfd);
   }

   new_mode = attr->statp.st_mode;
   Dmsg3(200, "type=%d newmode=%x file=%s\n", attr->type, new_mode, attr->ofname);
   parent_mode = S_IWUSR | S_IXUSR | new_mode;
   gid = attr->statp.st_gid;
   uid = attr->statp.st_uid;

#ifdef HAVE_WIN32
   if (!bfd->use_backup_api) {
      // eliminate invalid windows filename characters from foreign filenames
      char *ch = (char *)attr->ofname;
      if (ch[0] != 0 && ch[1] != 0) {
         ch += 2;
         while (*ch) {
            switch (*ch) {
            case ':':
            case '<':
            case '>':
            case '*':
            case '?':
            case '|':
               *ch = '_';
                break;
            }
            ch++;
         }
      }
   }
#endif

   Dmsg2(400, "Replace=%c %d\n", (char)replace, replace);
   if (lstat(attr->ofname, &mstatp) == 0) {
      exists = true;
      switch (replace) {
      case REPLACE_IFNEWER:
         if (attr->statp.st_mtime <= mstatp.st_mtime) {
            Qmsg(jcr, M_SKIPPED, 0, _("File skipped. Not newer: %s\n"), attr->ofname);
            return CF_SKIP;
         }
         break;

      case REPLACE_IFOLDER:
         if (attr->statp.st_mtime >= mstatp.st_mtime) {
            Qmsg(jcr, M_SKIPPED, 0, _("File skipped. Not older: %s\n"), attr->ofname);
            return CF_SKIP;
         }
         break;

      case REPLACE_NEVER:
         Qmsg(jcr, M_SKIPPED, 0, _("File skipped. Already exists: %s\n"), attr->ofname);
         return CF_SKIP;

      case REPLACE_ALWAYS:
         break;
      }
   }
   switch (attr->type) {
   case FT_RAW:                       /* raw device to be written */
   case FT_FIFO:                      /* FIFO to be written to */
   case FT_LNKSAVED:                  /* Hard linked, file already saved */
   case FT_LNK:
   case FT_SPEC:                      /* fifo, ... to be backed up */
   case FT_REGE:                      /* empty file */
   case FT_REG:                       /* regular file */
      /* 
       * Note, we do not delete FT_RAW because these are device files
       *  or FIFOs that should already exist. If we blow it away,
       *  we may blow away a FIFO that is being used to read the
       *  restore data, or we may blow away a partition definition.
       */
      if (exists && attr->type != FT_RAW && attr->type != FT_FIFO) {
         /* Get rid of old copy */
         Dmsg1(400, "unlink %s\n", attr->ofname);
         if (unlink(attr->ofname) == -1) {
            berrno be;
            Qmsg(jcr, M_ERROR, 0, _("File %s already exists and could not be replaced. ERR=%s.\n"),
               attr->ofname, be.bstrerror());
            /* Continue despite error */
         }
      }
      /*
       * Here we do some preliminary work for all the above
       *   types to create the path to the file if it does
       *   not already exist.  Below, we will split to
       *   do the file type specific work
       */
      pnl = separate_path_and_file(jcr, attr->fname, attr->ofname);
      if (pnl < 0) {
         return CF_ERROR;
      }

      /*
       * If path length is <= 0 we are making a file in the root
       *  directory. Assume that the directory already exists.
       */
      if (pnl > 0) {
         char savechr;
         savechr = attr->ofname[pnl];
         attr->ofname[pnl] = 0;                 /* terminate path */

         if (!path_already_seen(jcr, attr->ofname, pnl)) {
            Dmsg1(400, "Make path %s\n", attr->ofname);
            /*
             * If we need to make the directory, ensure that it is with
             * execute bit set (i.e. parent_mode), and preserve what already
             * exists. Normally, this should do nothing.
             */
            if (!makepath(attr, attr->ofname, parent_mode, parent_mode, uid, gid, 1)) {
               Dmsg1(10, "Could not make path. %s\n", attr->ofname);
               attr->ofname[pnl] = savechr;     /* restore full name */
               return CF_ERROR;
            }
         }
         attr->ofname[pnl] = savechr;           /* restore full name */
      }

      /* Now we do the specific work for each file type */
      switch(attr->type) {
      case FT_REGE:
      case FT_REG:
         Dmsg1(100, "Create=%s\n", attr->ofname);
         flags =  O_WRONLY | O_CREAT | O_TRUNC | O_BINARY; /*  O_NOFOLLOW; */
         if (IS_CTG(attr->statp.st_mode)) {
            flags |= O_CTG;              /* set contiguous bit if needed */
         }
         if (is_bopen(bfd)) {
            Qmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid);
            bclose(bfd);
         }
      

         if ((bopen(bfd, attr->ofname, flags, S_IRUSR | S_IWUSR)) < 0) {
            berrno be;
            be.set_errno(bfd->berrno);
            Qmsg2(jcr, M_ERROR, 0, _("Could not create %s: ERR=%s\n"),
                  attr->ofname, be.bstrerror());
            Dmsg2(100,"Could not create %s: ERR=%s\n", attr->ofname, be.bstrerror());
            return CF_ERROR;
         }
         return CF_EXTRACT;

#ifndef HAVE_WIN32  // none of these exists on MS Windows
      case FT_RAW:                    /* Bacula raw device e.g. /dev/sda1 */
      case FT_FIFO:                   /* Bacula fifo to save data */
      case FT_SPEC:
         if (S_ISFIFO(attr->statp.st_mode)) {
            Dmsg1(400, "Restore fifo: %s\n", attr->ofname);
            if (mkfifo(attr->ofname, attr->statp.st_mode) != 0 && errno != EEXIST) {
               berrno be;
               Qmsg2(jcr, M_ERROR, 0, _("Cannot make fifo %s: ERR=%s\n"),
                     attr->ofname, be.bstrerror());
               return CF_ERROR;
            }
         } else if (S_ISSOCK(attr->statp.st_mode)) {
             Dmsg1(200, "Skipping restore of socket: %s\n", attr->ofname);
#ifdef S_IFDOOR     // Solaris high speed RPC mechanism
         } else if (S_ISDOOR(attr->statp.st_mode)) {
             Dmsg1(200, "Skipping restore of door file: %s\n", attr->ofname);
#endif
#ifdef S_IFPORT     // Solaris event port for handling AIO
         } else if (S_ISPORT(attr->statp.st_mode)) {
             Dmsg1(200, "Skipping restore of event port file: %s\n", attr->ofname);
#endif
         } else {
            Dmsg1(400, "Restore node: %s\n", attr->ofname);
            if (mknod(attr->ofname, attr->statp.st_mode, attr->statp.st_rdev) != 0 && errno != EEXIST) {
               berrno be;
               Qmsg2(jcr, M_ERROR, 0, _("Cannot make node %s: ERR=%s\n"),
                     attr->ofname, be.bstrerror());
               return CF_ERROR;
            }
         }
         /*
          * Here we are going to attempt to restore to a FIFO, which
          *   means that the FIFO must already exist, AND there must
          *   be some process already attempting to read from the
          *   FIFO, so we open it write-only. 
          */
         if (attr->type == FT_RAW || attr->type == FT_FIFO) {
            btimer_t *tid;
            Dmsg1(400, "FT_RAW|FT_FIFO %s\n", attr->ofname);
            flags =  O_WRONLY | O_BINARY;
            /* Timeout open() in 60 seconds */
            if (attr->type == FT_FIFO) {
               Dmsg0(400, "Set FIFO timer\n");
               tid = start_thread_timer(jcr, pthread_self(), 60);
            } else {
               tid = NULL;
            }
            if (is_bopen(bfd)) {
               Qmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid);
            }
            Dmsg2(400, "open %s flags=0x%x\n", attr->ofname, flags);
            if ((bopen(bfd, attr->ofname, flags, 0)) < 0) {
               berrno be;
               be.set_errno(bfd->berrno);
               Qmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"),
                     attr->ofname, be.bstrerror());
               Dmsg2(400, "Could not open %s: ERR=%s\n", attr->ofname, be.bstrerror());
               stop_thread_timer(tid);
               return CF_ERROR;
            }
            stop_thread_timer(tid);
            return CF_EXTRACT;
         }
         Dmsg1(400, "FT_SPEC %s\n", attr->ofname);
         return CF_CREATED;

      case FT_LNK:
         Dmsg2(130, "FT_LNK should restore: %s -> %s\n", attr->ofname, attr->olname);
         if (symlink(attr->olname, attr->ofname) != 0 && errno != EEXIST) {
            berrno be;
            Qmsg3(jcr, M_ERROR, 0, _("Could not symlink %s -> %s: ERR=%s\n"),
                  attr->ofname, attr->olname, be.bstrerror());
            return CF_ERROR;
         }
         return CF_CREATED;

      case FT_LNKSAVED:                  /* Hard linked, file already saved */
         Dmsg2(130, "Hard link %s => %s\n", attr->ofname, attr->olname);
         if (link(attr->olname, attr->ofname) != 0) {
            berrno be;
#ifdef HAVE_CHFLAGS
            struct stat s;

        /*
            * If using BSD user flags, maybe has a file flag
            * preventing this. So attempt to disable, retry link,
            * and reset flags.
            * Note that BSD securelevel may prevent disabling flag.
        */

            if (stat(attr->olname, &s) == 0 && s.st_flags != 0) {
               if (chflags(attr->olname, 0) == 0) {
                  if (link(attr->olname, attr->ofname) != 0) {
                     /* restore original file flags even when linking failed */
                     if (chflags(attr->olname, s.st_flags) < 0) {
                        Qmsg2(jcr, M_ERROR, 0, _("Could not restore file flags for file %s: ERR=%s\n"),
                              attr->olname, be.bstrerror());
                     }
#endif /* HAVE_CHFLAGS */
            Qmsg3(jcr, M_ERROR, 0, _("Could not hard link %s -> %s: ERR=%s\n"),
                  attr->ofname, attr->olname, be.bstrerror());
            Dmsg3(200, "Could not hard link %s -> %s: ERR=%s\n",
                  attr->ofname, attr->olname, be.bstrerror());
            return CF_ERROR;
#ifdef HAVE_CHFLAGS
                  }
                  /* finally restore original file flags */
                  if (chflags(attr->olname, s.st_flags) < 0) {
                     Qmsg2(jcr, M_ERROR, 0, _("Could not restore file flags for file %s: ERR=%s\n"),
                            attr->olname, be.bstrerror());
                  }
               } else {
                 Qmsg2(jcr, M_ERROR, 0, _("Could not reset file flags for file %s: ERR=%s\n"),
                       attr->olname, be.bstrerror());
               }
            } else {
              Qmsg3(jcr, M_ERROR, 0, _("Could not hard link %s -> %s: ERR=%s\n"),
                    attr->ofname, attr->olname, be.bstrerror());
              return CF_ERROR;
            }
#endif /* HAVE_CHFLAGS */

         }
         return CF_CREATED;
#endif
      } /* End inner switch */

   case FT_REPARSE:
      bfd->reparse_point = true;
      /* Fall through wanted */
   case FT_DIRBEGIN:
   case FT_DIREND:
      Dmsg2(200, "Make dir mode=%o dir=%s\n", new_mode, attr->ofname);
      if (!makepath(attr, attr->ofname, new_mode, parent_mode, uid, gid, 0)) {
         return CF_ERROR;
      }
      /*
       * If we are using the Win32 Backup API, we open the
       *   directory so that the security info will be read
       *   and saved.
       */
      if (!is_portable_backup(bfd)) {
         if (is_bopen(bfd)) {
            Qmsg1(jcr, M_ERROR, 0, _("bpkt already open fid=%d\n"), bfd->fid);
         }
         if ((bopen(bfd, attr->ofname, O_WRONLY|O_BINARY, 0)) < 0) {
            berrno be;
            be.set_errno(bfd->berrno);
#ifdef HAVE_WIN32
            /* Check for trying to create a drive, if so, skip */
            if (attr->ofname[1] == ':' && 
                IsPathSeparator(attr->ofname[2]) && 
                attr->ofname[3] == '\0') {
               return CF_SKIP;
            }
#endif
            Qmsg2(jcr, M_ERROR, 0, _("Could not open %s: ERR=%s\n"),
                  attr->ofname, be.bstrerror());
            return CF_ERROR;
         }
         return CF_EXTRACT;
      } else {
         return CF_CREATED;
      }

   case FT_DELETED:
      Qmsg2(jcr, M_INFO, 0, _("Original file %s have been deleted: type=%d\n"), attr->fname, attr->type);
      break;
   /* The following should not occur */
   case FT_NOACCESS:
   case FT_NOFOLLOW:
   case FT_NOSTAT:
   case FT_DIRNOCHG:
   case FT_NOCHG:
   case FT_ISARCH:
   case FT_NORECURSE:
   case FT_NOFSCHG:
   case FT_NOOPEN:
      Qmsg2(jcr, M_ERROR, 0, _("Original file %s not saved: type=%d\n"), attr->fname, attr->type);
      break;
   default:
      Qmsg2(jcr, M_ERROR, 0, _("Unknown file type %d; not restored: %s\n"), attr->type, attr->fname);
      break;
   }
   return CF_ERROR;
}
Example #8
0
static int vma_get_mapfile(char *fname, struct vma_area *vma, DIR *mfd,
		struct vma_file_info *vfi, struct vma_file_info *prev_vfi)
{
	char path[32];

	if (prev_vfi->vma && vfi_equal(vfi, prev_vfi)) {
		struct vma_area *prev = prev_vfi->vma;

		/*
		 * If vfi is equal (!) and negative @vm_file_fd --
		 * we have nothing to borrow for sure.
		 */
		if (prev->vm_file_fd < 0)
			return 0;

		pr_debug("vma %"PRIx64" borrows vfi from previous %"PRIx64"\n",
				vma->e->start, prev->e->start);
		vma->vm_file_fd = prev->vm_file_fd;
		if (prev->e->status & VMA_AREA_SOCKET)
			vma->e->status |= VMA_AREA_SOCKET | VMA_AREA_REGULAR;

		/*
		 * FIXME -- in theory there can be vmas that have
		 * dev:ino match, but live in different mount
		 * namespaces. However, we only borrow files for
		 * subsequent vmas. These are _very_ likely to
		 * have files from the same namespaces.
		 */
		vma->file_borrowed = true;

		return 0;
	}

	/* Figure out if it's file mapping */
	snprintf(path, sizeof(path), "%"PRIx64"-%"PRIx64, vma->e->start, vma->e->end);

	/*
	 * Note that we "open" it in dumper process space
	 * so later we might refer to it via /proc/self/fd/vm_file_fd
	 * if needed.
	 */
	vma->vm_file_fd = openat(dirfd(mfd), path, O_RDONLY);
	if (vma->vm_file_fd < 0) {
		if (errno == ENOENT)
			/* Just mapping w/o map_files link */
			return 0;

		if (errno == ENXIO) {
			struct stat buf;

			if (fstatat(dirfd(mfd), path, &buf, 0))
				return -1;

			if (S_ISSOCK(buf.st_mode)) {
				pr_info("Found socket mapping @%"PRIx64"\n", vma->e->start);
				vma->vm_socket_id = buf.st_ino;
				vma->e->status |= VMA_AREA_SOCKET | VMA_AREA_REGULAR;
				return 0;
			}

			if ((buf.st_mode & S_IFMT) == 0 && !strcmp(fname, AIO_FNAME)) {
				/* AIO ring, let's try */
				close(vma->vm_file_fd);
				vma->aio_nr_req = -1;
				vma->e->status = VMA_AREA_AIORING;
				return 0;
			}

			pr_err("Unknown shit %o (%s)\n", buf.st_mode, fname);
		}

		return -1;
	}

	vma->vmst = xmalloc(sizeof(struct stat));
	if (!vma->vmst)
		return -1;

	/*
	 * For AUFS support, we need to check if the symbolic link
	 * points to a branch.  If it does, we cannot fstat() its file
	 * descriptor because it would return a different dev/ino than
	 * the real file.  If fixup_aufs_vma_fd() returns positive,
	 * it means that it has stat()'ed using the full pathname.
	 * Zero return means that the symbolic link does not point to
	 * a branch and we can do fstat() below.
	 */
	if (opts.aufs) {
		int ret;

		ret = fixup_aufs_vma_fd(vma);
		if (ret < 0)
			return -1;
		if (ret > 0)
			return 0;
	}

	if (fstat(vma->vm_file_fd, vma->vmst) < 0) {
		pr_perror("Failed fstat on map %"PRIx64"", vma->e->start);
		return -1;
	}

	return 0;
}
/* Return:
 * -1 error, copy not made
 *  0 copy is made or user answered "no" in interactive mode
 *    (failures to preserve mode/owner/times are not reported in exit code)
 */
int copy_file(const char *source, const char *dest, int flags)
{
	/* This is a recursive function, try to minimize stack usage */
	/* NB: each struct stat is ~100 bytes */
	struct stat source_stat;
	struct stat dest_stat;
	signed char retval = 0;
	signed char dest_exists = 0;
	signed char ovr;

/* Inverse of cp -d ("cp without -d") */
#define FLAGS_DEREF (flags & FILEUTILS_DEREFERENCE)

	if ((FLAGS_DEREF ? stat : lstat)(source, &source_stat) < 0) {
		// This may be a dangling symlink.
		// Making [sym]links to dangling symlinks works, so...
		if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK))
			goto make_links;
		bb_perror_msg("cannot stat '%s'", source);
		return -1;
	}

	if (lstat(dest, &dest_stat) < 0) {
		if (errno != ENOENT) {
			bb_perror_msg("cannot stat '%s'", dest);
			return -1;
		}
	} else {
		if (source_stat.st_dev == dest_stat.st_dev
		 && source_stat.st_ino == dest_stat.st_ino
		) {
			bb_error_msg("'%s' and '%s' are the same file", source, dest);
			return -1;
		}
		dest_exists = 1;
	}

#if ENABLE_SELINUX
	if ((flags & FILEUTILS_PRESERVE_SECURITY_CONTEXT) && is_selinux_enabled() > 0) {
		security_context_t con;
		if (lgetfilecon(source, &con) >= 0) {
			if (setfscreatecon(con) < 0) {
				bb_perror_msg("cannot set setfscreatecon %s", con);
				freecon(con);
				return -1;
			}
		} else if (errno == ENOTSUP || errno == ENODATA) {
			setfscreatecon_or_die(NULL);
		} else {
			bb_perror_msg("cannot lgetfilecon %s", source);
			return -1;
		}
	}
#endif

	if (S_ISDIR(source_stat.st_mode)) {
		DIR *dp;
		const char *tp;
		struct dirent *d;
		mode_t saved_umask = 0;

		if (!(flags & FILEUTILS_RECUR)) {
			bb_error_msg("omitting directory '%s'", source);
			return -1;
		}

		/* Did we ever create source ourself before? */
		tp = is_in_ino_dev_hashtable(&source_stat);
		if (tp) {
			/* We did! it's a recursion! man the lifeboats... */
			bb_error_msg("recursion detected, omitting directory '%s'",
					source);
			return -1;
		}

		/* Create DEST */
		if (dest_exists) {
			if (!S_ISDIR(dest_stat.st_mode)) {
				bb_error_msg("target '%s' is not a directory", dest);
				return -1;
			}
			/* race here: user can substitute a symlink between
			 * this check and actual creation of files inside dest */
		} else {
			mode_t mode;
			saved_umask = umask(0);

			mode = source_stat.st_mode;
			if (!(flags & FILEUTILS_PRESERVE_STATUS))
				mode = source_stat.st_mode & ~saved_umask;
			/* Allow owner to access new dir (at least for now) */
			mode |= S_IRWXU;
			if (mkdir(dest, mode) < 0) {
				umask(saved_umask);
				bb_perror_msg("cannot create directory '%s'", dest);
				return -1;
			}
			umask(saved_umask);
			/* need stat info for add_to_ino_dev_hashtable */
			if (lstat(dest, &dest_stat) < 0) {
				bb_perror_msg("cannot stat '%s'", dest);
				return -1;
			}
		}
		/* remember (dev,inode) of each created dir.
		 * NULL: name is not remembered */
		add_to_ino_dev_hashtable(&dest_stat, NULL);

		/* Recursively copy files in SOURCE */
		dp = opendir(source);
		if (dp == NULL) {
			retval = -1;
			goto preserve_mode_ugid_time;
		}

		while ((d = readdir(dp)) != NULL) {
			char *new_source, *new_dest;

			new_source = concat_subpath_file(source, d->d_name);
			if (new_source == NULL)
				continue;
			new_dest = concat_path_file(dest, d->d_name);
			if (copy_file(new_source, new_dest, flags) < 0)
				retval = -1;
			free(new_source);
			free(new_dest);
		}
		closedir(dp);

		if (!dest_exists
		 && chmod(dest, source_stat.st_mode & ~saved_umask) < 0
		) {
			bb_perror_msg("cannot preserve %s of '%s'", "permissions", dest);
			/* retval = -1; - WRONG! copy *WAS* made */
		}
		goto preserve_mode_ugid_time;
	}

	if (flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) {
		int (*lf)(const char *oldpath, const char *newpath);
 make_links:
		// Hmm... maybe
		// if (DEREF && MAKE_SOFTLINK) source = realpath(source) ?
		// (but realpath returns NULL on dangling symlinks...)
		lf = (flags & FILEUTILS_MAKE_SOFTLINK) ? symlink : link;
		if (lf(source, dest) < 0) {
			ovr = ask_and_unlink(dest, flags);
			if (ovr <= 0)
				return ovr;
			if (lf(source, dest) < 0) {
				bb_perror_msg("cannot create link '%s'", dest);
				return -1;
			}
		}
		/* _Not_ jumping to preserve_mode_ugid_time:
		 * hard/softlinks don't have those */
		return 0;
	}

	if (/* "cp thing1 thing2" without -R: just open and read() from thing1 */
	    !(flags & FILEUTILS_RECUR)
	    /* "cp [-opts] regular_file thing2" */
	 || S_ISREG(source_stat.st_mode)
	 /* DEREF uses stat, which never returns S_ISLNK() == true.
	  * So the below is never true: */
	 /* || (FLAGS_DEREF && S_ISLNK(source_stat.st_mode)) */
	) {
		int src_fd;
		int dst_fd;
		mode_t new_mode;

		if (!FLAGS_DEREF && S_ISLNK(source_stat.st_mode)) {
			/* "cp -d symlink dst": create a link */
			goto dont_cat;
		}

		if (ENABLE_FEATURE_PRESERVE_HARDLINKS && !FLAGS_DEREF) {
			const char *link_target;
			link_target = is_in_ino_dev_hashtable(&source_stat);
			if (link_target) {
				if (link(link_target, dest) < 0) {
					ovr = ask_and_unlink(dest, flags);
					if (ovr <= 0)
						return ovr;
					if (link(link_target, dest) < 0) {
						bb_perror_msg("cannot create link '%s'", dest);
						return -1;
					}
				}
				return 0;
			}
			add_to_ino_dev_hashtable(&source_stat, dest);
		}

		src_fd = open_or_warn(source, O_RDONLY);
		if (src_fd < 0)
			return -1;

		/* Do not try to open with weird mode fields */
		new_mode = source_stat.st_mode;
		if (!S_ISREG(source_stat.st_mode))
			new_mode = 0666;

		/* POSIX way is a security problem versus symlink attacks,
		 * we do it only for non-symlinks, and only for non-recursive,
		 * non-interactive cp. NB: it is still racy
		 * for "cp file /home/bad_user/file" case
		 * (user can rm file and create a link to /etc/passwd) */
		if (DO_POSIX_CP
		 || (dest_exists
		     && !(flags & (FILEUTILS_RECUR|FILEUTILS_INTERACTIVE))
		     && !S_ISLNK(dest_stat.st_mode))
		) {
			dst_fd = open(dest, O_WRONLY|O_CREAT|O_TRUNC, new_mode);
		} else  /* safe way: */
			dst_fd = open(dest, O_WRONLY|O_CREAT|O_EXCL, new_mode);
		if (dst_fd == -1) {
			ovr = ask_and_unlink(dest, flags);
			if (ovr <= 0) {
				close(src_fd);
				return ovr;
			}
			/* It shouldn't exist. If it exists, do not open (symlink attack?) */
			dst_fd = open3_or_warn(dest, O_WRONLY|O_CREAT|O_EXCL, new_mode);
			if (dst_fd < 0) {
				close(src_fd);
				return -1;
			}
		}

#if ENABLE_SELINUX
		if ((flags & (FILEUTILS_PRESERVE_SECURITY_CONTEXT|FILEUTILS_SET_SECURITY_CONTEXT))
		 && is_selinux_enabled() > 0
		) {
			security_context_t con;
			if (getfscreatecon(&con) == -1) {
				bb_perror_msg("getfscreatecon");
				return -1;
			}
			if (con) {
				if (setfilecon(dest, con) == -1) {
					bb_perror_msg("setfilecon:%s,%s", dest, con);
					freecon(con);
					return -1;
				}
				freecon(con);
			}
		}
#endif
		if (bb_copyfd_eof(src_fd, dst_fd) == -1)
			retval = -1;
		/* Ok, writing side I can understand... */
		if (close(dst_fd) < 0) {
			bb_perror_msg("cannot close '%s'", dest);
			retval = -1;
		}
		/* ...but read size is already checked by bb_copyfd_eof */
		close(src_fd);
		/* "cp /dev/something new_file" should not
		 * copy mode of /dev/something */
		if (!S_ISREG(source_stat.st_mode))
			return retval;
		goto preserve_mode_ugid_time;
	}
 dont_cat:

	/* Source is a symlink or a special file */
	/* We are lazy here, a bit lax with races... */
	if (dest_exists) {
		errno = EEXIST;
		ovr = ask_and_unlink(dest, flags);
		if (ovr <= 0)
			return ovr;
	}
	if (S_ISLNK(source_stat.st_mode)) {
		char *lpath = xmalloc_readlink_or_warn(source);
		if (lpath) {
			int r = symlink(lpath, dest);
			free(lpath);
			if (r < 0) {
				bb_perror_msg("cannot create symlink '%s'", dest);
				return -1;
			}
			if (flags & FILEUTILS_PRESERVE_STATUS)
				if (lchown(dest, source_stat.st_uid, source_stat.st_gid) < 0)
					bb_perror_msg("cannot preserve %s of '%s'", "ownership", dest);
		}
		/* _Not_ jumping to preserve_mode_ugid_time:
		 * symlinks don't have those */
		return 0;
	}
	if (S_ISBLK(source_stat.st_mode) || S_ISCHR(source_stat.st_mode)
	 || S_ISSOCK(source_stat.st_mode) || S_ISFIFO(source_stat.st_mode)
	) {
		if (mknod(dest, source_stat.st_mode, source_stat.st_rdev) < 0) {
			bb_perror_msg("cannot create '%s'", dest);
			return -1;
		}
	} else {
		bb_error_msg("unrecognized file '%s' with mode %x", source, source_stat.st_mode);
		return -1;
	}

 preserve_mode_ugid_time:

	if (flags & FILEUTILS_PRESERVE_STATUS
	/* Cannot happen: */
	/* && !(flags & (FILEUTILS_MAKE_SOFTLINK|FILEUTILS_MAKE_HARDLINK)) */
	) {
		struct utimbuf times;

		times.actime = source_stat.st_atime;
		times.modtime = source_stat.st_mtime;
		/* BTW, utimes sets usec-precision time - just FYI */
		if (utime(dest, &times) < 0)
			bb_perror_msg("cannot preserve %s of '%s'", "times", dest);
		if (chown(dest, source_stat.st_uid, source_stat.st_gid) < 0) {
			source_stat.st_mode &= ~(S_ISUID | S_ISGID);
			bb_perror_msg("cannot preserve %s of '%s'", "ownership", dest);
		}
		if (chmod(dest, source_stat.st_mode) < 0)
			bb_perror_msg("cannot preserve %s of '%s'", "permissions", dest);
	}

	return retval;
}
Example #10
0
/*
 * Add the file or dir hierarchy named by 'path' to the archive
 */
static void
write_hierarchy(struct bsdtar *bsdtar, struct archive *a, const char *path)
{
	struct archive_entry *entry = NULL, *spare_entry = NULL;
	struct tree *tree;
	char symlink_mode = bsdtar->symlink_mode;
	dev_t first_dev = 0;
	int dev_recorded = 0;
	int tree_ret;
	dev_t last_dev = 0;
	char * fstype;

	tree = tree_open(path);

	if (!tree) {
		bsdtar_warnc(bsdtar, errno, "%s: Cannot open", path);
		bsdtar->return_value = 1;
		return;
	}

	while ((tree_ret = tree_next(tree))) {
		int r;
		const char *name = tree_current_path(tree);
		const struct stat *st = NULL; /* info to use for this entry */
		const struct stat *lst = NULL; /* lstat() information */
		int descend;

		if (truncate_archive(bsdtar))
			break;
		if (checkpoint_archive(bsdtar, 0))
			exit(1);
		disk_pause(bsdtar);
		if (network_select(0))
			exit(1);

		if (tree_ret == TREE_ERROR_FATAL)
			bsdtar_errc(bsdtar, 1, tree_errno(tree),
			    "%s: Unable to continue traversing directory tree",
			    name);
		if (tree_ret == TREE_ERROR_DIR) {
			bsdtar_warnc(bsdtar, errno,
			    "%s: Couldn't visit directory", name);
			bsdtar->return_value = 1;
		}
		if (tree_ret != TREE_REGULAR)
			continue;

		/*
		 * If this file/dir is excluded by a filename
		 * pattern, skip it.
		 */
		if (excluded(bsdtar, name))
			continue;

		/*
		 * Get lstat() info from the tree library.
		 */
		lst = tree_current_lstat(tree);
		if (lst == NULL) {
			/* Couldn't lstat(); must not exist. */
			bsdtar_warnc(bsdtar, errno, "%s: Cannot stat", name);
			/* Return error if files disappear during traverse. */
			bsdtar->return_value = 1;
			continue;
		}

		/*
		 * Distinguish 'L'/'P'/'H' symlink following.
		 */
		switch(symlink_mode) {
		case 'H':
			/* 'H': After the first item, rest like 'P'. */
			symlink_mode = 'P';
			/* 'H': First item (from command line) like 'L'. */
			/* FALLTHROUGH */
		case 'L':
			/* 'L': Do descend through a symlink to dir. */
			descend = tree_current_is_dir(tree);
			/* 'L': Follow symlinks to files. */
			archive_read_disk_set_symlink_logical(bsdtar->diskreader);
			/* 'L': Archive symlinks as targets, if we can. */
			st = tree_current_stat(tree);
			if (st != NULL)
				break;
			/* If stat fails, we have a broken symlink;
			 * in that case, don't follow the link. */
			/* FALLTHROUGH */
		default:
			/* 'P': Don't descend through a symlink to dir. */
			descend = tree_current_is_physical_dir(tree);
			/* 'P': Don't follow symlinks to files. */
			archive_read_disk_set_symlink_physical(bsdtar->diskreader);
			/* 'P': Archive symlinks as symlinks. */
			st = lst;
			break;
		}

		if (bsdtar->option_no_subdirs)
			descend = 0;

		/*
		 * If user has asked us not to cross mount points,
		 * then don't descend into a dir on a different
		 * device.
		 */
		if (!dev_recorded) {
			last_dev = first_dev = lst->st_dev;
			dev_recorded = 1;
		}
		if (bsdtar->option_dont_traverse_mounts) {
			if (lst->st_dev != first_dev)
				descend = 0;
		}

		/*
		 * If the user did not specify --insane-filesystems, do not
		 * cross into a new filesystem which is known to be synthetic.
		 * Note that we will archive synthetic filesystems if we are
		 * explicitly told to do so.
		 */
		if ((bsdtar->option_insane_filesystems == 0) &&
		    (descend != 0) &&
		    (lst->st_dev != last_dev)) {
			fstype = getfstype(tree_current_access_path(tree));
			if (fstype == NULL)
				bsdtar_errc(bsdtar, 1, errno,
				    "%s: Error getting filesystem type",
				    name);
			if (getfstype_issynthetic(fstype)) {
				if (!bsdtar->option_quiet)
					bsdtar_warnc(bsdtar, 0,
					    "Not descending into filesystem of type %s: %s",
					    fstype, name);
				descend = 0;
			} else {
				/* This device is ok to archive. */
				last_dev = lst->st_dev;
			}
			free(fstype);
		}

		/*
		 * In -u mode, check that the file is newer than what's
		 * already in the archive; in all modes, obey --newerXXX flags.
		 */
		if (!new_enough(bsdtar, name, st)) {
			if (!descend)
				continue;
			if (bsdtar->option_interactive &&
			    !yes("add '%s'", name))
				continue;
			tree_descend(tree);
			continue;
		}

		archive_entry_free(entry);
		entry = archive_entry_new();

		archive_entry_set_pathname(entry, name);
		archive_entry_copy_sourcepath(entry,
		    tree_current_access_path(tree));

		/* Populate the archive_entry with metadata from the disk. */
		/* XXX TODO: Arrange to open a regular file before
		 * calling this so we can pass in an fd and shorten
		 * the race to query metadata.  The linkify dance
		 * makes this more complex than it might sound. */
		r = archive_read_disk_entry_from_file(bsdtar->diskreader,
		    entry, -1, st);
		if (r != ARCHIVE_OK)
			bsdtar_warnc(bsdtar, archive_errno(bsdtar->diskreader),
			    "%s", archive_error_string(bsdtar->diskreader));
		if (r < ARCHIVE_WARN)
			continue;

		/* XXX TODO: Just use flag data from entry; avoid the
		 * duplicate check here. */

		/*
		 * If this file/dir is flagged "nodump" and we're
		 * honoring such flags, skip this file/dir.
		 */
#if defined(HAVE_STRUCT_STAT_ST_FLAGS) && defined(UF_NODUMP)
		/* BSD systems store flags in struct stat */
		if (bsdtar->option_honor_nodump &&
		    (lst->st_flags & UF_NODUMP))
			continue;
#endif

#if defined(EXT2_NODUMP_FL)
		/* Linux uses ioctl to read flags. */
		if (bsdtar->option_honor_nodump) {
			unsigned long fflags, dummy;
			archive_entry_fflags(entry, &fflags, &dummy);
			if (fflags & EXT2_NODUMP_FL)
				continue;
		}
#endif

		/*
		 * Don't back up the cache directory or any files inside it.
		 */
		if ((lst->st_ino == bsdtar->cachedir_ino) &&
		    (lst->st_dev == bsdtar->cachedir_dev)) {
			if (!bsdtar->option_quiet)
				bsdtar_warnc(bsdtar, 0,
				    "Not adding cache directory to archive: %s",
				name);
			continue;
		}

		/*
		 * If the user vetoes this file/directory, skip it.
		 * We want this to be fairly late; if some other
		 * check would veto this file, we shouldn't bother
		 * the user with it.
		 */
		if (bsdtar->option_interactive &&
		    !yes("add '%s'", name))
			continue;

		/* Note: if user vetoes, we won't descend. */
		if (descend)
			tree_descend(tree);

		/*
		 * Rewrite the pathname to be archived.  If rewrite
		 * fails, skip the entry.
		 */
		if (edit_pathname(bsdtar, entry))
			continue;

		/*
		 * If this is a socket, skip the entry: POSIX requires that
		 * pax(1) emit a "diagnostic message" (i.e., warning) that
		 * sockets cannot be archived, but this can make backups of
		 * running systems very noisy.
		 */
		if (S_ISSOCK(st->st_mode))
			continue;

		/* Display entry as we process it.
		 * This format is required by SUSv2. */
		if (bsdtar->verbose)
			safe_fprintf(stderr, "a %s",
			    archive_entry_pathname(entry));

		/*
		 * If the user hasn't specifically asked to have the access
		 * time stored, zero it.  At the moment this usually only
		 * matters for files which have flags set, since the "posix
		 * restricted" format doesn't store access times for most
		 * other files.
		 */
		if (bsdtar->option_store_atime == 0)
			archive_entry_set_atime(entry, 0, 0);

		/* Non-regular files get archived with zero size. */
		if (!S_ISREG(st->st_mode))
			archive_entry_set_size(entry, 0);

		/* Record what we're doing, for SIGINFO / SIGUSR1. */
		siginfo_setinfo(bsdtar, "adding",
		    archive_entry_pathname(entry), archive_entry_size(entry));
		archive_entry_linkify(bsdtar->resolver, &entry, &spare_entry);

		/* Handle SIGINFO / SIGUSR1 request if one was made. */
		siginfo_printinfo(bsdtar, 0);

		while (entry != NULL) {
			write_entry_backend(bsdtar, a, entry, st,
			    tree_current_realpath(tree));
			archive_entry_free(entry);
			entry = spare_entry;
			spare_entry = NULL;
		}

		if (bsdtar->verbose)
			fprintf(stderr, "\n");
	}
	archive_entry_free(entry);
	if (tree_close(tree))
		bsdtar_errc(bsdtar, 1, 0, "Error traversing directory tree");
}
Example #11
0
VistaIOBoolean VistaIOIdentifyFiles (int noptions, VistaIOOptionDescRec options[],
			 VistaIOStringConst keyword, int *argc, char **argv, int fd)
{
	VistaIOOptionDescRec *opt;
	VistaIOArgVector *vec;
	VistaIOBoolean switch_found = FALSE;
	VistaIOStringConst *values;
	struct stat stat_buf;
	int i, j, n;

	/* A -in or -out switch on the command line may specify one or more
	   files. Look for the switch's entry in the option table supplied: */
	for (i = 0, opt = options; i < noptions; i++, opt++)
		if (strcmp (keyword, opt->keyword) == 0)
			break;
	if (i == noptions)
		VistaIOError ("VistaIOIdentifyFiles: Option -%s not defined in option table", keyword);

	/* The option table entry must specify a location for storing filenames: */
	if (!opt->value)
		VistaIOError ("VistaIOIdentifyFiles: No value storage for option -%s",
			keyword);
	vec = ((VistaIOArgVector *) opt->value);

	/* Whether or not the option was present on the command line should have
	   been recorded in a "found" flag: */
	if (opt->found && opt->found != VistaIORequiredOpt
	    && opt->found != VistaIOOptionalOpt)
		switch_found = *(opt->found);
	else
		VistaIOError ("VistaIOIdentifyFiles: No \"found\" flag for option -%s",
			keyword);

	/* If a -in or -out switch was specified, it supplies the files' names: */
	if (switch_found)
		return TRUE;

	/* If no switch was specified but some extra arguments were supplied
	   with the command, those arguments should be the files' names: */
	if (*argc > 1) {

		/* If any number are permitted, allocate storage for all of them: */
		if (opt->number == 0) {
			vec->vector =
				VistaIOMalloc ((*argc - 1) * sizeof (VistaIOStringConst));
			values = (VistaIOStringConst *) vec->vector;
		} else
			values = (VistaIOStringConst *) opt->value;

		/* Accept arguments as filenames provided they don't begin with
		   a single -: */
		for (i = j = 1, n = 0; i < *argc; i++)
			if ((argv[i][0] == '-' && argv[i][1] != '-') ||
			    (opt->number && n == opt->number))
				argv[j++] = argv[i];	/* not a filename */
			else if (argv[i][0] == '-' && argv[i][1] == '-')
				values[n++] = argv[i] + 1;	/* filename with -- prefix */
			else
				values[n++] = argv[i];	/* filename */

		/* Ensure that a sufficient number were supplied: */
		if (n) {
			if (opt->number) {
				if (n != opt->number) {
					if (opt->number == 1) {
						goto WrongNumber1;
					} else {
						goto WrongNumberN;
					}
				}
			} else
				vec->number = n;
			*argc = j;
			return TRUE;
		}
	}

	/* That leaves only an open file descriptor as the file. In that case
	   there can be at most one such file: */
	if (opt->number > 1) {
	      WrongNumberN:
		fprintf (stderr, "%s: %d files must be specified by -%s or "
			 "extra command arguments.\n", argv[0], opt->number,
			 keyword);
		return FALSE;
	}

	/* If a particular file descriptor is specified by fd, ensure that it
	   is connected to a pipe or file (not the terminal): */
	if (fd >= 0) {
		if (fstat (fd, &stat_buf) == -1)
			VistaIOSystemError ("Failed to fstat() fd %d", fd);
		if (!S_ISREG (stat_buf.st_mode)
#ifdef S_ISSOCK
/* The ISSOCK macro is only available in POSIX_STDC;
   beware of problems with piping files if this line is omited */
		    && !S_ISSOCK (stat_buf.st_mode)
#endif
		    && !S_ISLNK (stat_buf.st_mode)
		    && !S_ISFIFO (stat_buf.st_mode)) {
		      WrongNumber1:
			fprintf (stderr,
				 "%s: No file specified by -%s, extra command "
				 "argument, or %c.\n", argv[0], keyword,
				 "<>"[fd]);
			return FALSE;
		}
	}

	/* Record the file as being "-": */
	if (opt->number == 0) {
		vec->number = 1;
		vec->vector = VistaIOMalloc (sizeof (VistaIOStringConst));
		((VistaIOStringConst *) vec->vector)[0] = "-";
	} else
		*((VistaIOStringConst *) opt->value) = "-";
	return TRUE;
}
Example #12
0
int
epoll_ctl(int fd, int op, int fd2, struct epoll_event *ev)
{
	struct kevent kev[2];
	uint16_t flags;
	int e;

	if ((!ev && op != EPOLL_CTL_DEL) ||
	    (ev &&
		((ev->events &
		    ~(EPOLLIN | EPOLLOUT | EPOLLHUP | EPOLLRDHUP | EPOLLERR))
		    /* the user should really set one of EPOLLIN or EPOLLOUT
		     * so that EPOLLHUP and EPOLLERR work. Don't make this a
		     * hard error for now, though. */
		    /* || !(ev->events & (EPOLLIN | EPOLLOUT)) */))) {
		errno = EINVAL;
		return (-1);
	}

	if (fd2 < 0 || ((uint32_t)fd2 & ~(((uint32_t)1 << KEY_BITS) - 1))) {
		errno = EBADF;
		return (-1);
	}

	if ((e = kqueue_load_state(fd, fd2, &flags)) < 0) {
		errno = e;
		return (-1);
	}

	if (op == EPOLL_CTL_ADD) {
		if (flags & KQUEUE_STATE_REGISTERED) {
			errno = EEXIST;
			return (-1);
		}

		EV_SET(&kev[0], fd2, EVFILT_READ,
		    EV_ADD | (ev->events & EPOLLIN ? 0 : EV_DISABLE), 0, 0,
		    ev->data.ptr);
		EV_SET(&kev[1], fd2, EVFILT_WRITE,
		    EV_ADD | (ev->events & EPOLLOUT ? 0 : EV_DISABLE), 0, 0,
		    ev->data.ptr);

		flags = KQUEUE_STATE_REGISTERED;

#define SET_FLAG(flag)                                                        \
	do {                                                                  \
		if (ev->events & (flag)) {                                    \
			flags |= KQUEUE_STATE_##flag;                         \
		}                                                             \
	} while (0)

		SET_FLAG(EPOLLIN);
		SET_FLAG(EPOLLOUT);
		SET_FLAG(EPOLLRDHUP);

#undef SET_FLAG

	} else if (op == EPOLL_CTL_DEL) {
		if (poll_fd == fd2 && fd == poll_epoll_fd) {
			poll_fd = -1;
			poll_epoll_fd = -1;
			poll_ptr = NULL;
			return 0;
		}

		if (!(flags & KQUEUE_STATE_REGISTERED)) {
			errno = ENOENT;
			return (-1);
		}

		EV_SET(&kev[0], fd2, EVFILT_READ, EV_DELETE, 0, 0, 0);
		EV_SET(&kev[1], fd2, EVFILT_WRITE, EV_DELETE, 0, 0, 0);

		flags = 0;
	} else if (op == EPOLL_CTL_MOD) {
		if (!(flags & KQUEUE_STATE_REGISTERED)) {
			errno = ENOENT;
			return (-1);
		}

		EV_SET(&kev[0], fd2, EVFILT_READ,
		    ev->events & EPOLLIN ? EV_ENABLE : EV_DISABLE, 0, 0,
		    ev->data.ptr);
		EV_SET(&kev[1], fd2, EVFILT_WRITE,
		    ev->events & EPOLLOUT ? EV_ENABLE : EV_DISABLE, 0, 0,
		    ev->data.ptr);

#define SET_FLAG(flag)                                                        \
	do {                                                                  \
		if (ev->events & (flag)) {                                    \
			flags |= KQUEUE_STATE_##flag;                         \
		} else {                                                      \
			flags &= ~KQUEUE_STATE_##flag;                        \
		}                                                             \
	} while (0)

		SET_FLAG(EPOLLIN);
		SET_FLAG(EPOLLOUT);
		SET_FLAG(EPOLLRDHUP);

#undef SET_FLAG

	} else {
		errno = EINVAL;
		return (-1);
	}

	for (int i = 0; i < 2; ++i) {
		kev[i].flags |= EV_RECEIPT;
	}

	int ret = kevent(fd, kev, 2, kev, 2, NULL);
	if (ret < 0) {
		return -1;
	}

	if (ret != 2) {
		errno = EINVAL;
		return -1;
	}

	for (int i = 0; i < 2; ++i) {
		if (!(kev[i].flags & EV_ERROR)) {
			errno = EINVAL;
			return -1;
		}

		if (kev[i].data == ENODEV && poll_fd < 0) {
			poll_fd = fd2;
			poll_epoll_fd = fd;
			poll_ptr = ev->data.ptr;
			return 0;
		}

		/*
		 * Ignore EVFILT_WRITE registration EINVAL errors (some fd
		 * types such as kqueues themselves don't support it).
		 * Also ignore ENOENT -- this happens when trying to remove a
		 * previously added fd where the EVFILT_WRITE registration
		 * failed.
		 */
		if (i == 1 &&
		    (kev[i].data == EINVAL || kev[i].data == ENOENT)) {
			continue;
		}

		if (kev[i].data != 0) {
			errno = kev[i].data;
			return -1;
		}
	}

	if (op != EPOLL_CTL_DEL && is_not_yet_connected_stream_socket(fd2)) {
		EV_SET(&kev[0], fd2, EVFILT_READ, EV_ENABLE | EV_FORCEONESHOT,
		    0, 0, ev->data.ptr);
		if (kevent(fd, kev, 1, NULL, 0, NULL) < 0) {
			return -1;
		}

		flags |= KQUEUE_STATE_NYCSS;
	}

	struct stat statbuf;
	if (fstat(fd2, &statbuf) < 0) {
		return -1;
	}

	if (S_ISFIFO(statbuf.st_mode)) {
		flags |= KQUEUE_STATE_ISFIFO;
	} else if (S_ISSOCK(statbuf.st_mode)) {
		flags |= KQUEUE_STATE_ISSOCK;
	}

	if ((e = kqueue_save_state(fd, fd2, flags)) < 0) {
		errno = e;
		return (-1);
	}

	return 0;
}
Example #13
0
struct device *
ether_Create(struct physical *p)
{
  u_char rbuf[2048];
  struct etherdevice *dev;
  struct ng_mesg *resp;
  const struct hooklist *hlist;
  const struct nodeinfo *ninfo;
  char *path, *sessionid;
  int ifacelen, f;

  dev = NULL;
  path = NULL;
  ifacelen = 0;
  if (p->fd < 0 && !strncasecmp(p->name.full, NG_PPPOE_NODE_TYPE,
                                PPPOE_NODE_TYPE_LEN) &&
      p->name.full[PPPOE_NODE_TYPE_LEN] == ':') {
    const struct linkinfo *nlink;
    struct ngpppoe_init_data *data;
    struct ngm_mkpeer mkp;
    struct ngm_connect ngc;
    const char *iface, *provider;
    char etherid[12];
    int providerlen;
    char connectpath[sizeof dev->hook + 2];	/* .:<hook> */

    p->fd--;				/* We own the device - change fd */

    loadmodules(LOAD_VERBOSLY, "netgraph", "ng_ether", "ng_pppoe", "ng_socket",
                NULL);

    if ((dev = malloc(sizeof *dev)) == NULL)
      return NULL;

    iface = p->name.full + PPPOE_NODE_TYPE_LEN + 1;

    provider = strchr(iface, ':');
    if (provider) {
      ifacelen = provider - iface;
      provider++;
      providerlen = strlen(provider);
    } else {
      ifacelen = strlen(iface);
      provider = "";
      providerlen = 0;
    }

    /*
     * We're going to do this (where tunN is our tunnel device):
     *
     * .---------.
     * |  ether  |
     * | <iface> |                         dev->cs
     * `---------'                           |
     *  (orphan)                     p->fd   |
     *     |                           |     |
     *     |                           |     |
     * (ethernet)                      |     |
     * .---------.                  .-----------.
     * |  pppoe  |                  |  socket   |
     * | <iface> |(tunN)<---->(tunN)| <unnamed> |
     * `---------                   `-----------'
     *   (tunX)
     *     ^
     *     |
     *     `--->(tunX)
     */

    /* Create a socket node */
    if (ID0NgMkSockNode(NULL, &dev->cs, &p->fd) == -1) {
      log_Printf(LogWARN, "Cannot create netgraph socket node: %s\n",
                 strerror(errno));
      free(dev);
      p->fd = -2;
      return NULL;
    }

    /*
     * Ask for a list of hooks attached to the "ether" node.  This node should
     * magically exist as a way of hooking stuff onto an ethernet device
     */
    path = (char *)alloca(ifacelen + 2);
    snprintf(path, ifacelen + 2, "%.*s:", ifacelen, iface);
    if (NgSendMsg(dev->cs, path, NGM_GENERIC_COOKIE, NGM_LISTHOOKS,
                  NULL, 0) < 0) {
      log_Printf(LogWARN, "%s Cannot send a netgraph message: %s\n",
                 path, strerror(errno));
      return ether_Abandon(dev, p);
    }

    /* Get our list back */
    resp = (struct ng_mesg *)rbuf;
    if (NgRecvMsg(dev->cs, resp, sizeof rbuf, NULL) <= 0) {
      log_Printf(LogWARN, "Cannot get netgraph response: %s\n",
                 strerror(errno));
      return ether_Abandon(dev, p);
    }

    hlist = (const struct hooklist *)resp->data;
    ninfo = &hlist->nodeinfo;

    /* Make sure we've got the right type of node */
    if (strncmp(ninfo->type, NG_ETHER_NODE_TYPE,
                sizeof NG_ETHER_NODE_TYPE - 1)) {
      log_Printf(LogWARN, "%s Unexpected node type ``%s'' (wanted ``"
                 NG_ETHER_NODE_TYPE "'')\n", path, ninfo->type);
      return ether_Abandon(dev, p);
    }

    log_Printf(LogDEBUG, "List of netgraph node ``%s'' (id %x) hooks:\n",
               path, ninfo->id);

    /* look for a hook already attached.  */
    for (f = 0; f < ninfo->hooks; f++) {
      nlink = &hlist->link[f];

      log_Printf(LogDEBUG, "  Found %s -> %s\n", nlink->ourhook,
                 nlink->peerhook);

      if (!strcmp(nlink->ourhook, NG_ETHER_HOOK_ORPHAN) ||
          !strcmp(nlink->ourhook, NG_ETHER_HOOK_DIVERT)) {
        /*
         * Something is using the data coming out of this ``ether'' node.
         * If it's a PPPoE node, we use that node, otherwise we complain that
         * someone else is using the node.
         */
        if (!strcmp(nlink->nodeinfo.type, NG_PPPOE_NODE_TYPE))
          /* Use this PPPoE node ! */
          snprintf(ngc.path, sizeof ngc.path, "[%x]:", nlink->nodeinfo.id);
        else {
          log_Printf(LogWARN, "%s Node type ``%s'' is currently active\n",
                     path, nlink->nodeinfo.type);
          return ether_Abandon(dev, p);
        }
        break;
      }
    }

    if (f == ninfo->hooks) {
      /*
       * Create a new ``PPPoE'' node connected to the ``ether'' node using
       * the ``orphan'' and ``ethernet'' hooks
       */
      snprintf(mkp.type, sizeof mkp.type, "%s", NG_PPPOE_NODE_TYPE);
      snprintf(mkp.ourhook, sizeof mkp.ourhook, "%s", NG_ETHER_HOOK_ORPHAN);
      snprintf(mkp.peerhook, sizeof mkp.peerhook, "%s", NG_PPPOE_HOOK_ETHERNET);
      snprintf(etherid, sizeof etherid, "[%x]:", ninfo->id);

      log_Printf(LogDEBUG, "Creating PPPoE netgraph node %s%s -> %s\n",
                 etherid, mkp.ourhook, mkp.peerhook);

      if (NgSendMsg(dev->cs, etherid, NGM_GENERIC_COOKIE,
                    NGM_MKPEER, &mkp, sizeof mkp) < 0) {
        log_Printf(LogWARN, "%s Cannot create PPPoE netgraph node: %s\n",
                   etherid, strerror(errno));
        return ether_Abandon(dev, p);
      }

      snprintf(ngc.path, sizeof ngc.path, "%s%s", path, NG_ETHER_HOOK_ORPHAN);
    }

    snprintf(dev->hook, sizeof dev->hook, "%s%d",
             TUN_NAME, p->dl->bundle->unit);

    /*
     * Connect the PPPoE node to our socket node.
     * ngc.path has already been set up
     */
    snprintf(ngc.ourhook, sizeof ngc.ourhook, "%s", dev->hook);
    memcpy(ngc.peerhook, ngc.ourhook, sizeof ngc.peerhook);

    log_Printf(LogDEBUG, "Connecting netgraph socket .:%s -> %s:%s\n",
               ngc.ourhook, ngc.path, ngc.peerhook);
    if (NgSendMsg(dev->cs, ".:", NGM_GENERIC_COOKIE,
                  NGM_CONNECT, &ngc, sizeof ngc) < 0) {
      log_Printf(LogWARN, "Cannot connect PPPoE and socket netgraph "
                 "nodes: %s\n", strerror(errno));
      return ether_Abandon(dev, p);
    }

    /* Bring the Ethernet interface up */
    path[ifacelen] = '\0';	/* Remove the trailing ':' */
    if (!iface_SetFlags(path, IFF_UP))
      log_Printf(LogWARN, "%s: Failed to set the IFF_UP flag on %s\n",
                 p->link.name, path);

    /* And finally, request a connection to the given provider */

    data = (struct ngpppoe_init_data *)alloca(sizeof *data + providerlen);
    snprintf(data->hook, sizeof data->hook, "%s", dev->hook);
    memcpy(data->data, provider, providerlen);
    data->data_len = providerlen;

    snprintf(connectpath, sizeof connectpath, ".:%s", dev->hook);
    log_Printf(LogDEBUG, "Sending PPPOE_CONNECT to %s\n", connectpath);
    if (NgSendMsg(dev->cs, connectpath, NGM_PPPOE_COOKIE,
                  NGM_PPPOE_CONNECT, data, sizeof *data + providerlen) == -1) {
      log_Printf(LogWARN, "``%s'': Cannot start netgraph node: %s\n",
                 connectpath, strerror(errno));
      return ether_Abandon(dev, p);
    }

    /* Hook things up so that we monitor dev->cs */
    p->desc.UpdateSet = ether_UpdateSet;
    p->desc.IsSet = ether_IsSet;
    p->desc.Read = ether_DescriptorRead;

    memcpy(&dev->dev, &baseetherdevice, sizeof dev->dev);
    switch (p->cfg.cd.necessity) {
      case CD_VARIABLE:
        dev->dev.cd.delay = p->cfg.cd.delay;
        break;
      case CD_REQUIRED:
        dev->dev.cd = p->cfg.cd;
        break;
      case CD_NOTREQUIRED:
        log_Printf(LogWARN, "%s: Carrier must be set, using ``set cd %d!''\n",
                   p->link.name, dev->dev.cd.delay);
      case CD_DEFAULT:
        break;
    }

    dev->timeout = dev->dev.cd.delay;
    dev->connected = CARRIER_PENDING;
    /* This will be overridden by our session id - if provided by netgraph */
    dev->slot = GetIfIndex(path);
  } else {
    /* See if we're a netgraph socket */
    struct stat st;

    if (fstat(p->fd, &st) != -1 && S_ISSOCK(st.st_mode)) {
      struct sockaddr_storage ssock;
      struct sockaddr *sock = (struct sockaddr *)&ssock;
      int sz;

      sz = sizeof ssock;
      if (getsockname(p->fd, sock, &sz) == -1) {
        log_Printf(LogPHASE, "%s: Link is a closed socket !\n", p->link.name);
        close(p->fd);
        p->fd = -1;
        return NULL;
      }

      if (sock->sa_family == AF_NETGRAPH) {
        /*
         * It's a netgraph node... We can't determine hook names etc, so we
         * stay pretty impartial....
         */
        log_Printf(LogPHASE, "%s: Link is a netgraph node\n", p->link.name);

        if ((dev = malloc(sizeof *dev)) == NULL) {
          log_Printf(LogWARN, "%s: Cannot allocate an ether device: %s\n",
                     p->link.name, strerror(errno));
          return NULL;
        }

        memcpy(&dev->dev, &baseetherdevice, sizeof dev->dev);
        dev->cs = -1;
        dev->timeout = 0;
        dev->connected = CARRIER_OK;
        *dev->hook = '\0';

        /*
         * If we're being envoked from pppoed(8), we may have a SESSIONID
         * set in the environment.  If so, use it as the slot
         */
        if ((sessionid = getenv("SESSIONID")) != NULL) {
          char *end;
          u_long slot;

          slot = strtoul(sessionid, &end, 16);
          dev->slot = end != sessionid && *end == '\0' ? slot : 0;
        } else
          dev->slot = 0;
      }
    }
  }

  if (dev) {
    physical_SetupStack(p, dev->dev.name, PHYSICAL_FORCE_SYNCNOACF);
    return &dev->dev;
  }

  return NULL;
}
Example #14
0
/* open the file and mmap it, necessary to go to READY state */
static gboolean
gst_file_src_start (GstBaseSrc * basesrc)
{
  GstFileSrc *src = GST_FILE_SRC (basesrc);
  struct stat stat_results;

  if (src->filename == NULL || src->filename[0] == '\0')
    goto no_filename;

  GST_INFO_OBJECT (src, "opening file %s", src->filename);

  /* open the file */
  src->fd = gst_open (src->filename, O_RDONLY | O_BINARY, 0);

  if (src->fd < 0)
    goto open_failed;

  /* check if it is a regular file, otherwise bail out */
  if (fstat (src->fd, &stat_results) < 0)
    goto no_stat;

  if (S_ISDIR (stat_results.st_mode))
    goto was_directory;

  if (S_ISSOCK (stat_results.st_mode))
    goto was_socket;

  src->using_mmap = FALSE;
  src->read_position = 0;

  /* record if it's a regular (hence seekable and lengthable) file */
  if (S_ISREG (stat_results.st_mode))
    src->is_regular = TRUE;

#ifdef HAVE_MMAP
  if (src->use_mmap) {
    /* FIXME: maybe we should only try to mmap if it's a regular file */
    /* allocate the first mmap'd region if it's a regular file ? */
    src->mapbuf = gst_file_src_map_region (src, 0, src->mapsize, TRUE);
    if (src->mapbuf != NULL) {
      GST_DEBUG_OBJECT (src, "using mmap for file");
      src->using_mmap = TRUE;
      src->seekable = TRUE;
    }
  }
  if (src->mapbuf == NULL)
#endif
  {
    /* If not in mmap mode, we need to check if the underlying file is
     * seekable. */
    off_t res = lseek (src->fd, 0, SEEK_END);

    if (res < 0) {
      GST_LOG_OBJECT (src, "disabling seeking, not in mmap mode and lseek "
          "failed: %s", g_strerror (errno));
      src->seekable = FALSE;
    } else {
      src->seekable = TRUE;
    }
    lseek (src->fd, 0, SEEK_SET);
  }

  /* We can only really do seeking on regular files - for other file types, we
   * don't know their length, so seeking isn't useful/meaningful */
  src->seekable = src->seekable && src->is_regular;

  return TRUE;

  /* ERROR */
no_filename:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,
        (_("No file name specified for reading.")), (NULL));
    return FALSE;
  }
open_failed:
  {
    switch (errno) {
      case ENOENT:
        GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL),
            ("No such file \"%s\"", src->filename));
        break;
      default:
        GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
            (_("Could not open file \"%s\" for reading."), src->filename),
            GST_ERROR_SYSTEM);
        break;
    }
    return FALSE;
  }
no_stat:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
        (_("Could not get info on \"%s\"."), src->filename), (NULL));
    close (src->fd);
    return FALSE;
  }
was_directory:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
        (_("\"%s\" is a directory."), src->filename), (NULL));
    close (src->fd);
    return FALSE;
  }
was_socket:
  {
    GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ,
        (_("File \"%s\" is a socket."), src->filename), (NULL));
    close (src->fd);
    return FALSE;
  }
}
Example #15
0
static int
NativeMatchType(
    Tcl_Interp *interp,       /* Interpreter to receive errors. */
    CONST char *nativeEntry,  /* Native path to check. */
    CONST char *nativeName,   /* Native filename to check. */
    Tcl_GlobTypeData *types)  /* Type description to match against. */
{
    Tcl_StatBuf buf;
    if (types == NULL) {
	/*
	 * Simply check for the file's existence, but do it with lstat, in
	 * case it is a link to a file which doesn't exist (since that case
	 * would not show up if we used 'access' or 'stat')
	 */

	if (TclOSlstat(nativeEntry, &buf) != 0) {
	    return 0;
	}
    } else {
	if (types->perm != 0) {
	    if (TclOSstat(nativeEntry, &buf) != 0) {
		/*
		 * Either the file has disappeared between the 'readdir' call
		 * and the 'stat' call, or the file is a link to a file which
		 * doesn't exist (which we could ascertain with lstat), or
		 * there is some other strange problem. In all these cases, we
		 * define this to mean the file does not match any defined
		 * permission, and therefore it is not added to the list of
		 * files to return.
		 */

		return 0;
	    }

	    /*
	     * readonly means that there are NO write permissions (even for
	     * user), but execute is OK for anybody OR that the user immutable
	     * flag is set (where supported).
	     */

	    if (((types->perm & TCL_GLOB_PERM_RONLY) &&
#if defined(HAVE_CHFLAGS) && defined(UF_IMMUTABLE)
			!(buf.st_flags & UF_IMMUTABLE) &&
#endif
			(buf.st_mode & (S_IWOTH|S_IWGRP|S_IWUSR))) ||
		((types->perm & TCL_GLOB_PERM_R) &&
			(access(nativeEntry, R_OK) != 0)) ||
		((types->perm & TCL_GLOB_PERM_W) &&
			(access(nativeEntry, W_OK) != 0)) ||
		((types->perm & TCL_GLOB_PERM_X) &&
			(access(nativeEntry, X_OK) != 0))
#ifndef MAC_OSX_TCL
		|| ((types->perm & TCL_GLOB_PERM_HIDDEN) &&
			(*nativeName != '.'))
#endif
		) {
		return 0;
	    }
	}
	if (types->type != 0) {
	    if (types->perm == 0) {
		/*
		 * We haven't yet done a stat on the file.
		 */

		if (TclOSstat(nativeEntry, &buf) != 0) {
		    /*
		     * Posix error occurred. The only ok case is if this is a
		     * link to a nonexistent file, and the user did 'glob -l'.
		     * So we check that here:
		     */

		    if (types->type & TCL_GLOB_TYPE_LINK) {
			if (TclOSlstat(nativeEntry, &buf) == 0) {
			    if (S_ISLNK(buf.st_mode)) {
				return 1;
			    }
			}
		    }
		    return 0;
		}
	    }

	    /*
	     * In order bcdpfls as in 'find -t'
	     */

	    if (((types->type & TCL_GLOB_TYPE_BLOCK)&& S_ISBLK(buf.st_mode)) ||
		((types->type & TCL_GLOB_TYPE_CHAR) && S_ISCHR(buf.st_mode)) ||
		((types->type & TCL_GLOB_TYPE_DIR)  && S_ISDIR(buf.st_mode)) ||
		((types->type & TCL_GLOB_TYPE_PIPE) && S_ISFIFO(buf.st_mode))||
		((types->type & TCL_GLOB_TYPE_FILE) && S_ISREG(buf.st_mode))
#ifdef S_ISSOCK
		||((types->type & TCL_GLOB_TYPE_SOCK) && S_ISSOCK(buf.st_mode))
#endif /* S_ISSOCK */
		) {
		/*
		 * Do nothing - this file is ok.
		 */
	    } else {
#ifdef S_ISLNK
		if (types->type & TCL_GLOB_TYPE_LINK) {
		    if (TclOSlstat(nativeEntry, &buf) == 0) {
			if (S_ISLNK(buf.st_mode)) {
			    goto filetypeOK;
			}
		    }
		}
#endif /* S_ISLNK */
		return 0;
	    }
	}
    filetypeOK: ;
#ifdef MAC_OSX_TCL
	if (types->macType != NULL || types->macCreator != NULL ||
		(types->perm & TCL_GLOB_PERM_HIDDEN)) {
	    int matchResult;

	    if (types->perm == 0 && types->type == 0) {
		/*
		 * We haven't yet done a stat on the file.
		 */

		if (TclOSstat(nativeEntry, &buf) != 0) {
		    return 0;
		}
	    }

	    matchResult = TclMacOSXMatchType(interp, nativeEntry, nativeName,
		    &buf, types);
	    if (matchResult != 1) {
		return matchResult;
	    }
	}
#endif
    }
    return 1;
}
Example #16
0
static unsigned int parse_directory(struct entry *root_entry, const char *name, struct entry **prev, loff_t *fslen_ub)
{
	struct dirent **dirlist;
	int totalsize = 0, dircount, dirindex;
	char *path, *endpath;
	size_t len = strlen(name);

	/* Set up the path. */
	/* TODO: Reuse the parent's buffer to save memcpy'ing and duplication. */
	path = malloc(len + 1 + MAX_INPUT_NAMELEN + 1);
	if (!path) {
		perror(NULL);
		exit(8);
	}
	memcpy(path, name, len);
	endpath = path + len;
	*endpath = '/';
	endpath++;

        /* read in the directory and sort */
        dircount = scandir(name, &dirlist, 0, cramsort);

	if (dircount < 0) {
		perror(name);
		exit(8);
	}

	/* process directory */
	for (dirindex = 0; dirindex < dircount; dirindex++) {
		struct dirent *dirent;
		struct entry *entry;
		struct stat st;
		int size;
		size_t namelen;

		dirent = dirlist[dirindex];

		/* Ignore "." and ".." - we won't be adding them to the archive */
		if (dirent->d_name[0] == '.') {
			if (dirent->d_name[1] == '\0')
				continue;
			if (dirent->d_name[1] == '.') {
				if (dirent->d_name[2] == '\0')
					continue;
			}
		}
		namelen = strlen(dirent->d_name);
		if (namelen > MAX_INPUT_NAMELEN) {
			fprintf(stderr,
				"Very long (%u bytes) filename `%s' found.\n"
				" Please increase MAX_INPUT_NAMELEN in mkcramfs.c and recompile.  Exiting.\n",
				namelen, dirent->d_name);
			exit(8);
		}
		memcpy(endpath, dirent->d_name, namelen + 1);

		if (lstat(path, &st) < 0) {
			perror(endpath);
			warn_skip = 1;
			continue;
		}
		entry = calloc(1, sizeof(struct entry));
		if (!entry) {
			perror(NULL);
			exit(8);
		}
		entry->name = strdup(dirent->d_name);
		if (!entry->name) {
			perror(NULL);
			exit(8);
		}
		if (namelen > 255) {
			/* Can't happen when reading from ext2fs. */

			/* TODO: we ought to avoid chopping in half
			   multi-byte UTF8 characters. */
			entry->name[namelen = 255] = '\0';
			warn_namelen = 1;
		}
		entry->mode = st.st_mode;
		entry->size = st.st_size;
		entry->uid = st.st_uid;
		if (entry->uid >= 1 << CRAMFS_UID_WIDTH)
			warn_uid = 1;
		entry->gid = st.st_gid;
		if (entry->gid >= 1 << CRAMFS_GID_WIDTH)
			/* TODO: We ought to replace with a default
                           gid instead of truncating; otherwise there
                           are security problems.  Maybe mode should
                           be &= ~070.  Same goes for uid once Linux
                           supports >16-bit uids. */
			warn_gid = 1;
		size = sizeof(struct cramfs_inode) + ((namelen + 3) & ~3);
		*fslen_ub += size;
		if (S_ISDIR(st.st_mode)) {
			entry->size = parse_directory(root_entry, path, &entry->child, fslen_ub);
		} else if (S_ISREG(st.st_mode)) {
			/* TODO: We ought to open files in do_compress, one
			   at a time, instead of amassing all these memory
			   maps during parse_directory (which don't get used
			   until do_compress anyway).  As it is, we tend to
			   get EMFILE errors (especially if mkcramfs is run
			   by non-root).

			   While we're at it, do analagously for symlinks
			   (which would just save a little memory). */
			int fd = open(path, O_RDONLY);
			if (fd < 0) {
				perror(path);
				warn_skip = 1;
				continue;
			}
			if (entry->size) {
				if ((entry->size >= 1 << CRAMFS_SIZE_WIDTH)) {
					warn_size = 1;
					entry->size = (1 << CRAMFS_SIZE_WIDTH) - 1;
				}

				entry->uncompressed = mmap(NULL, entry->size, PROT_READ, MAP_PRIVATE, fd, 0);
				if (-1 == (int) (long) entry->uncompressed) {
					perror("mmap");
					exit(8);
				}
			}
			close(fd);
		} else if (S_ISLNK(st.st_mode)) {
			entry->uncompressed = malloc(entry->size);
			if (!entry->uncompressed) {
				perror(NULL);
				exit(8);
			}
			if (readlink(path, entry->uncompressed, entry->size) < 0) {
				perror(path);
				warn_skip = 1;
				continue;
			}
		} else if (S_ISFIFO(st.st_mode) || S_ISSOCK(st.st_mode)) {
			/* maybe we should skip sockets */
			entry->size = 0;
		} else {
			entry->size = st.st_rdev;
			if (entry->size & -(1<<CRAMFS_SIZE_WIDTH))
				warn_dev = 1;
		}

		if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
			int blocks = ((entry->size - 1) / blksize + 1);

			/* block pointers & data expansion allowance + data */
			if(entry->size)
				*fslen_ub += (4+26)*blocks + entry->size + 3;
                }

		if (opt_xip && entry->mode & S_ISVTX) {
			/* worse case, depending on where the offsets falls,
			 * a single XIP entry could expand the sizeof the
			 * file system by 8k, since we're aligning the start
			 * and end on page boundary.
			 */
			*fslen_ub += 2*PAGE_CACHE_SIZE;
		}

		/* Link it into the list */
		*prev = entry;
		prev = &entry->next;
		totalsize += size;
	}
	free(path);
	free(dirlist);		/* allocated by scandir() with malloc() */
	return totalsize;
}
Example #17
0
static int
getentropy_fallback(void *buf, size_t len)
{
	uint8_t results[SHA512_DIGEST_LENGTH];
	int save_errno = errno, e, pgs = sysconf(_SC_PAGESIZE), faster = 0, repeat;
	static int cnt;
	struct timespec ts;
	struct timeval tv;
	struct pst_vminfo pvi;
	struct pst_vm_status pvs;
	struct pst_dynamic pdy;
	struct rusage ru;
	sigset_t sigset;
	struct stat st;
	SHA512_CTX ctx;
	static pid_t lastpid;
	pid_t pid;
	size_t i, ii, m;
	char *p;

	pid = getpid();
	if (lastpid == pid) {
		faster = 1;
		repeat = 2;
	} else {
		faster = 0;
		lastpid = pid;
		repeat = REPEAT;
	}
	for (i = 0; i < len; ) {
		int j;
		SHA512_Init(&ctx);
		for (j = 0; j < repeat; j++) {
			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
			if (e != -1) {
				cnt += (int)tv.tv_sec;
				cnt += (int)tv.tv_usec;
			}

			HX(pstat_getvminfo(&pvi, sizeof(pvi), 1, 0) != 1, pvi);
			HX(pstat_getprocvm(&pvs, sizeof(pvs), 0, 0) != 1, pvs);

			for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
				HX(clock_gettime(cl[ii], &ts) == -1, ts);

			HX((pid = getpid()) == -1, pid);
			HX((pid = getsid(pid)) == -1, pid);
			HX((pid = getppid()) == -1, pid);
			HX((pid = getpgid(0)) == -1, pid);
			HX((e = getpriority(0, 0)) == -1, e);

			if(pstat_getdynamic(&pdy, sizeof(pdy), 1, 0) != 1) {
				HD(errno);
			} else {
				HD(pdy.psd_avg_1_min);
				HD(pdy.psd_avg_5_min);
				HD(pdy.psd_avg_15_min);
			}

			if (!faster) {
				ts.tv_sec = 0;
				ts.tv_nsec = 1;
				(void) nanosleep(&ts, NULL);
			}

			HX(sigpending(&sigset) == -1, sigset);
			HX(sigprocmask(SIG_BLOCK, NULL, &sigset) == -1,
			    sigset);

			HF(getentropy);	/* an addr in this library */
			HF(printf);		/* an addr in libc */
			p = (char *)&p;
			HD(p);		/* an addr on stack */
			p = (char *)&errno;
			HD(p);		/* the addr of errno */

			if (i == 0) {
				struct sockaddr_storage ss;
				struct statvfs stvfs;
				struct termios tios;
				socklen_t ssl;
				off_t off;

				/*
				 * Prime-sized mappings encourage fragmentation;
				 * thus exposing some address entropy.
				 */
				struct mm {
					size_t	npg;
					void	*p;
				} mm[] =	 {
					{ 17, MAP_FAILED }, { 3, MAP_FAILED },
					{ 11, MAP_FAILED }, { 2, MAP_FAILED },
					{ 5, MAP_FAILED }, { 3, MAP_FAILED },
					{ 7, MAP_FAILED }, { 1, MAP_FAILED },
					{ 57, MAP_FAILED }, { 3, MAP_FAILED },
					{ 131, MAP_FAILED }, { 1, MAP_FAILED },
				};

				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
					HX(mm[m].p = mmap(NULL,
					    mm[m].npg * pgs,
					    PROT_READ|PROT_WRITE,
					    MAP_PRIVATE|MAP_ANON, -1,
					    (off_t)0), mm[m].p);
					if (mm[m].p != MAP_FAILED) {
						size_t mo;

						/* Touch some memory... */
						p = mm[m].p;
						mo = cnt %
						    (mm[m].npg * pgs - 1);
						p[mo] = 1;
						cnt += (int)((long)(mm[m].p)
						    / pgs);
					}

					/* Check cnts and times... */
					for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]);
					    ii++) {
						HX((e = clock_gettime(cl[ii],
						    &ts)) == -1, ts);
						if (e != -1)
							cnt += (int)ts.tv_nsec;
					}

					HX((e = getrusage(RUSAGE_SELF,
					    &ru)) == -1, ru);
					if (e != -1) {
						cnt += (int)ru.ru_utime.tv_sec;
						cnt += (int)ru.ru_utime.tv_usec;
					}
				}

				for (m = 0; m < sizeof mm/sizeof(mm[0]); m++) {
					if (mm[m].p != MAP_FAILED)
						munmap(mm[m].p, mm[m].npg * pgs);
					mm[m].p = MAP_FAILED;
				}

				HX(stat(".", &st) == -1, st);
				HX(statvfs(".", &stvfs) == -1, stvfs);

				HX(stat("/", &st) == -1, st);
				HX(statvfs("/", &stvfs) == -1, stvfs);

				HX((e = fstat(0, &st)) == -1, st);
				if (e == -1) {
					if (S_ISREG(st.st_mode) ||
					    S_ISFIFO(st.st_mode) ||
					    S_ISSOCK(st.st_mode)) {
						HX(fstatvfs(0, &stvfs) == -1,
						    stvfs);
						HX((off = lseek(0, (off_t)0,
						    SEEK_CUR)) < 0, off);
					}
					if (S_ISCHR(st.st_mode)) {
						HX(tcgetattr(0, &tios) == -1,
						    tios);
					} else if (S_ISSOCK(st.st_mode)) {
						memset(&ss, 0, sizeof ss);
						ssl = sizeof(ss);
						HX(getpeername(0,
						    (void *)&ss, &ssl) == -1,
						    ss);
					}
				}

				HX((e = getrusage(RUSAGE_CHILDREN,
				    &ru)) == -1, ru);
				if (e != -1) {
					cnt += (int)ru.ru_utime.tv_sec;
					cnt += (int)ru.ru_utime.tv_usec;
				}
			} else {
				/* Subsequent hashes absorb previous result */
				HD(results);
			}

			HX((e = gettimeofday(&tv, NULL)) == -1, tv);
			if (e != -1) {
				cnt += (int)tv.tv_sec;
				cnt += (int)tv.tv_usec;
			}

			HD(cnt);
		}
		SHA512_Final(results, &ctx);
		memcpy((char *)buf + i, results, min(sizeof(results), len - i));
		i += min(sizeof(results), len - i);
	}
	explicit_bzero(&ctx, sizeof ctx);
	explicit_bzero(results, sizeof results);
	if (gotdata(buf, len) == 0) {
		errno = save_errno;
		return 0;		/* satisfied */
	}
	errno = EIO;
	return -1;
}
Example #18
0
int ino_to_fileinfo(
                       struct inode *pino,
                       char *databuf,
                       UINT32 maxlen,
                       PUINT32 plen,
                       unsigned short level,
                       unsigned short flags,
                       unsigned short attrs,
                       struct dirent *pDir,
                       INT32 position, int TypeOp)
{
    pCommonFileInfo pCommon;
    pFileName pFile;
    PINT32 pPosition;

    *plen = 0;

/***************************************************************************/
/*** First field : long position if FF_GETPOS - nothing if FF_NOPOS      ***/
/***************************************************************************/
    if (TypeOp == TYPEOP_FILEFIND)
    {
        if (flags == FF_GETPOS)
        {
            if (sizeof(INT32) + *plen > maxlen)
            {
                fs_log("ino_to_fileinfo() - Buffer overflow for first field");
                return ERROR_BUFFER_OVERFLOW;
            }
            pPosition = (PINT32) (databuf + *plen);
            *pPosition = position;
            *plen += sizeof(INT32);
        }
    }
/***************************************************************************/

/***************************************************************************/
/*** Second field : common file information to all level/flags           ***/
/***************************************************************************/
    if (sizeof(CommonFileInfo) + *plen > maxlen)
    {
        kernel_printf("ino_to_fileinfo() - Buffer overflow for second field - len = %lu - maxlen = %lu", (UINT32) sizeof(CommonFileInfo) + (UINT32) (*plen), (UINT32) maxlen);
        return ERROR_BUFFER_OVERFLOW;
    }
    pCommon = (pCommonFileInfo) (databuf + *plen);

    date_unix2dos(pino->i_ctime, &(pCommon->timeCreate), &(pCommon->dateCreate));
    date_unix2dos(pino->i_atime, &(pCommon->timeAccess), &(pCommon->dateAccess));
    date_unix2dos(pino->i_mtime, &(pCommon->timeWrite), &(pCommon->dateWrite));
    pCommon->cbEOF = pino->i_size;
    pCommon->cbAlloc = pino->i_blocks;
    pCommon->attr = FILE_NORMAL;

    if ((S_ISLNK(pino->i_mode)) ||
        (S_ISBLK(pino->i_mode)) ||
        (S_ISCHR(pino->i_mode)) ||
        (S_ISFIFO(pino->i_mode)) ||
        (S_ISSOCK(pino->i_mode)))
    {
        pCommon->attr |= FILE_SYSTEM;
/*** UNIXish special files are seen as SYSTEM files ***/
    }                           /* endif */

    if (S_ISDIR(pino->i_mode))
    {
        pCommon->attr |= FILE_DIRECTORY;
    }                           /* endif */

    if ((!(pino->i_mode & S_IWUSR)) &&
        (!(pino->i_mode & S_IWGRP)) &&
        (!(pino->i_mode & S_IWOTH)))
    {
        pCommon->attr |= FILE_READONLY;
    }
    *plen += sizeof(CommonFileInfo);
/***************************************************************************/

/***************************************************************************/
/*** Third field : nothing for level FIL_STANDARD                        ***/
/***************************************************************************/
/***************************************************************************/

/***************************************************************************/
/*** Third field : Size on disk of EA set for FIL_QUERYEASIZE            ***/
/***************************************************************************/
    if (level == FIL_QUERYEASIZE)
    {
        if (sizeof(INT32) + *plen > maxlen)
        {
            fs_log("ino_to_fileinfo() - Buffer overflow for Third field - FIL_QUERYEASIZE");
            return ERROR_BUFFER_OVERFLOW;
        }
        *((PINT32) (databuf + *plen)) = 0;
/*** No EAS in ext2 ***/
        *plen += sizeof(INT32);
    }
/***************************************************************************/

/***************************************************************************/
/*** Third field : FEAList for level QUERYEASFROMLIST                    ***/
/***************************************************************************/
    if (level == FIL_QUERYEASFROMLIST)
    {
        if (sizeof(INT32) + *plen > maxlen)
        {
            fs_log("ino_to_fileinfo() - Buffer overflow for Third field - FIL_QUERYEASFROMLIST");
            return ERROR_BUFFER_OVERFLOW;
        }
        *((PINT32) (databuf + *plen)) = 4;  /*** No EAS in ext2 ***//* this is the length field of FEAList */
        *plen += sizeof(INT32);
    }
/***************************************************************************/

/***************************************************************************/
/*** Fourth field : name                                                 ***/
/***************************************************************************/
    if (TypeOp == TYPEOP_FILEFIND)
    {
        if (*plen + sizeof(FileName) + pDir->d_reclen > maxlen)
        {
            fs_log("ino_to_fileinfo() - Buffer overflow for fourth field");
            return ERROR_BUFFER_OVERFLOW;
        }
        pFile = (pFileName) (databuf + *plen);
        pFile->cbName = (unsigned char)pDir->d_reclen;  /* name length WITHOUT '\0' */
        strcpy(pFile->szName, pDir->d_name);    /* name WITH '\0'           */
        *plen += sizeof(FileName) + pDir->d_reclen;     /* sizeof(FileName) + strlen(Dir.d_name) */
    }
/***************************************************************************/

    return NO_ERROR;
}
static unsigned int walk_directory(struct imgspec* const spec,
	struct hostprog_path* const path, struct entry** previous)
{
	struct dirent** dirlst;
	int dirlst_count;
	int dirlst_index;
	
	__u64 dir_sz = 0;
	__u64 dir_lvl = hostprog_path_lvls(path);
	
	dirlst_count = scandir(path->p_path, &dirlst, NULL, hostprog_scandirsort);
	if (dirlst_count < 0)
		error("failed to read \"%s\": %s", path->p_path, strerror(errno));
	
	for (dirlst_index = 0; dirlst_index < dirlst_count; dirlst_index++) {
		struct dirent* dent = dirlst[dirlst_index];
		
		/* Skip "." and ".." directories, just like mkcramfs.
		 */
		if (hostprog_path_dotdir(dent->d_name))
			continue;
		
		hostprog_path_dirnamelvl(path, dir_lvl);
		if (hostprog_path_append(path, dent->d_name) != 0)
			error("failed to add a filename to the hostprog_path");
		
		struct stat st;
		if (lstat(path->p_path, &st) < 0) {
			/* Maybe this should be an error? Files missing in the image
			 * could possibly seem like an error to the user.
			 */
			warning("skipping \"unlstatable\" file \"%s\": %s",
				path->p_path, strerror(errno));
			spec->sp_skipnodes++;
			continue;
		}
		
		if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
			/* If the file is a regular file which can not be read, then
			 * it might as well be skipped.
			 * 
			 * This should also possibly be an error.
			 */
			if (access(path->p_path, R_OK) < 0) {
				warning("skipping unreadable file \"%s\": %s",
					path->p_path, strerror(errno));
				spec->sp_skipnodes++;
				continue;
			}
			/* Completely empty files seems pretty pointless to include
			 * in the image.
			 */
			if (!st.st_size) {
				message(VERBOSITY_1, ">>> skipping empty file \"%s\"", path->p_path);
				spec->sp_skipnodes++;
				continue;
			}
		} else if (!spec->sp_incsocks && S_ISSOCK(st.st_mode)) {
			warning("skipping socket \"%s\"", path->p_path);
			spec->sp_skipnodes++;
			continue;
		}
		
		/* Files should never be skipped after this point since that
		 * would mess up the image size estimation.
		 */
		
		struct entry* ent = malloc(sizeof(*ent));
		if (!ent)
			error("failed to alloc an entry for \"%s\"", path->p_path);
		
		memset(ent, 0, sizeof(*ent));
		
		ent->e_name = strdup(dent->d_name);
		if (!ent->e_name)
			error("failed to copy the entry name for \"%s\"", path->p_path);
		ent->e_mode = st.st_mode;
		ent->e_size = st.st_size;
		ent->e_fd = -1;
		
		ENTRY_SET_XID(spec, ent, e_uid, st.st_uid, MICROFS_IUID_WIDTH);
		ENTRY_SET_XID(spec, ent, e_gid, st.st_gid, MICROFS_IGID_WIDTH);
		
		if (S_ISDIR(ent->e_mode)) {
			ent->e_size = walk_directory(spec, path, &ent->e_firstchild);
		} else if (S_ISREG(ent->e_mode) || S_ISLNK(ent->e_mode)) {
			if (ent->e_size > MICROFS_MAXFILESIZE) {
				error("\"%s\" is too big, max file size is %llu bytes",
					path->p_path, MICROFS_MAXFILESIZE);
			} else if (ent->e_size > MICROFS_MAXCRAMSIZE) {
				warning("\"%s\" is a big file, microfs works best with files"
					" smaller than %llu bytes",
					path->p_path, MICROFS_MAXCRAMSIZE);
			}
			ent->e_path = strdup(path->p_path);
			if (!ent->e_path) {
				error("failed to copy the entry path for \"%s\"",
					path->p_path);
			}
			if (spec->sp_shareblocks) {
				if (hostprog_stack_push(spec->sp_regstack, ent) < 0)
					error("failed to push an entry to the regular file stack: %s",
						strerror(errno));
			}
		} else if (S_ISCHR(ent->e_mode) || S_ISBLK(ent->e_mode)) {
			ent->e_size = makedev_lim(major(st.st_rdev), minor(st.st_rdev),
				MICROFS_ISIZE_WIDTH);
		} else if (S_ISFIFO(ent->e_mode) || S_ISSOCK(ent->e_mode)) {
			ent->e_size = 0;
		} else {
			error("unexpected file mode encountered");
		}
		
		/* %namelen() could actually fail here if the d_name is too
		 * long, but that will terminate the program, so that is fine.
		 */
		dir_sz += update_upperbound(spec, ent, namelen(dent->d_name));
		
		update_stats(spec, ent);
		
		message(VERBOSITY_1, "+ %c %s", nodtype(ent->e_mode), path->p_path);
		
		*previous = ent;
		previous = &ent->e_sibling;
	}
	
	free(dirlst);
	hostprog_path_dirnamelvl(path, dir_lvl);
	
	/* This should never happen, but if it ever does, it is
	 * clearly an error.
	 */
	if (dir_sz > MICROFS_MAXDIRSIZE) {
		error("achievement unlocked: the directory size for \"%s\""
			" is %llu bytes, the maximum supported size is %llu bytes"
			" - this is impressive in a very scary way",
			path->p_path, dir_sz, MICROFS_MAXDIRSIZE);
	}
	
	return dir_sz;
}
Example #20
0
char const *
file_type (struct stat const *st)
{
  /* See POSIX 1003.1-2001 XCU Table 4-8 lines 17093-17107 for some of
     these formats.

     To keep diagnostics grammatical in English, the returned string
     must start with a consonant.  */

  /* Do these three first, as they're the most common.  */

  if (S_ISREG (st->st_mode))
    return st->st_size == 0 ? _("regular empty file") : _("regular file");

  if (S_ISDIR (st->st_mode))
    return _("directory");

  if (S_ISLNK (st->st_mode))
    return _("symbolic link");

  /* Do the S_TYPEIS* macros next, as they may be implemented in terms
     of S_ISNAM, and we want the more-specialized interpretation.  */

  if (S_TYPEISMQ (st))
    return _("message queue");

  if (S_TYPEISSEM (st))
    return _("semaphore");

  if (S_TYPEISSHM (st))
    return _("shared memory object");

  if (S_TYPEISTMO (st))
    return _("typed memory object");

  /* The remaining are in alphabetical order.  */

  if (S_ISBLK (st->st_mode))
    return _("block special file");

  if (S_ISCHR (st->st_mode))
    return _("character special file");

  if (S_ISCTG (st->st_mode))
    return _("contiguous data");

  if (S_ISFIFO (st->st_mode))
    return _("fifo");

  if (S_ISDOOR (st->st_mode))
    return _("door");

  if (S_ISMPB (st->st_mode))
    return _("multiplexed block special file");

  if (S_ISMPC (st->st_mode))
    return _("multiplexed character special file");

  if (S_ISMPX (st->st_mode))
    return _("multiplexed file");

  if (S_ISNAM (st->st_mode))
    return _("named file");

  if (S_ISNWK (st->st_mode))
    return _("network special file");

  if (S_ISOFD (st->st_mode))
    return _("migrated file with data");

  if (S_ISOFL (st->st_mode))
    return _("migrated file without data");

  if (S_ISPORT (st->st_mode))
    return _("port");

  if (S_ISSOCK (st->st_mode))
    return _("socket");

  if (S_ISWHT (st->st_mode))
    return _("whiteout");

  return _("weird file");
}
Example #21
0
/*
 * Get a new inode.
 */
struct inode * 
ncp_iget(struct super_block *sb, struct ncp_entry_info *info)
{
	struct inode *inode;

	if (info == NULL) {
		printk(KERN_ERR "ncp_iget: info is NULL\n");
		return NULL;
	}

	inode = new_inode(sb);
	if (inode) {
		atomic_set(&NCP_FINFO(inode)->opened, info->opened);

		inode->i_mapping->backing_dev_info = sb->s_bdi;
		inode->i_ino = info->ino;
		ncp_set_attr(inode, info);
		if (S_ISREG(inode->i_mode)) {
			inode->i_op = &ncp_file_inode_operations;
			inode->i_fop = &ncp_file_operations;
		} else if (S_ISDIR(inode->i_mode)) {
			inode->i_op = &ncp_dir_inode_operations;
			inode->i_fop = &ncp_dir_operations;
#ifdef CONFIG_NCPFS_NFS_NS
		} else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) {
			init_special_inode(inode, inode->i_mode,
				new_decode_dev(info->i.nfs.rdev));
#endif
#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS)
		} else if (S_ISLNK(inode->i_mode)) {
			inode->i_op = &ncp_symlink_inode_operations;
			inode->i_data.a_ops = &ncp_symlink_aops;
#endif
		} else {
			make_bad_inode(inode);
		}
		insert_inode_hash(inode);
	} else
		printk(KERN_ERR "ncp_iget: iget failed!\n");
	return inode;
}
Example #22
0
File: inode.c Project: 020gzh/linux
void hpfs_read_inode(struct inode *i)
{
	struct buffer_head *bh;
	struct fnode *fnode;
	struct super_block *sb = i->i_sb;
	struct hpfs_inode_info *hpfs_inode = hpfs_i(i);
	void *ea;
	int ea_size;

	if (!(fnode = hpfs_map_fnode(sb, i->i_ino, &bh))) {
		/*i->i_mode |= S_IFREG;
		i->i_mode &= ~0111;
		i->i_op = &hpfs_file_iops;
		i->i_fop = &hpfs_file_ops;
		clear_nlink(i);*/
		make_bad_inode(i);
		return;
	}
	if (hpfs_sb(i->i_sb)->sb_eas) {
		if ((ea = hpfs_get_ea(i->i_sb, fnode, "UID", &ea_size))) {
			if (ea_size == 2) {
				i_uid_write(i, le16_to_cpu(*(__le16*)ea));
				hpfs_inode->i_ea_uid = 1;
			}
			kfree(ea);
		}
		if ((ea = hpfs_get_ea(i->i_sb, fnode, "GID", &ea_size))) {
			if (ea_size == 2) {
				i_gid_write(i, le16_to_cpu(*(__le16*)ea));
				hpfs_inode->i_ea_gid = 1;
			}
			kfree(ea);
		}
		if ((ea = hpfs_get_ea(i->i_sb, fnode, "SYMLINK", &ea_size))) {
			kfree(ea);
			i->i_mode = S_IFLNK | 0777;
			i->i_op = &page_symlink_inode_operations;
			inode_nohighmem(i);
			i->i_data.a_ops = &hpfs_symlink_aops;
			set_nlink(i, 1);
			i->i_size = ea_size;
			i->i_blocks = 1;
			brelse(bh);
			return;
		}
		if ((ea = hpfs_get_ea(i->i_sb, fnode, "MODE", &ea_size))) {
			int rdev = 0;
			umode_t mode = hpfs_sb(sb)->sb_mode;
			if (ea_size == 2) {
				mode = le16_to_cpu(*(__le16*)ea);
				hpfs_inode->i_ea_mode = 1;
			}
			kfree(ea);
			i->i_mode = mode;
			if (S_ISBLK(mode) || S_ISCHR(mode)) {
				if ((ea = hpfs_get_ea(i->i_sb, fnode, "DEV", &ea_size))) {
					if (ea_size == 4)
						rdev = le32_to_cpu(*(__le32*)ea);
					kfree(ea);
				}
			}
			if (S_ISBLK(mode) || S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) {
				brelse(bh);
				set_nlink(i, 1);
				i->i_size = 0;
				i->i_blocks = 1;
				init_special_inode(i, mode,
					new_decode_dev(rdev));
				return;
			}
		}
	}
	if (fnode_is_dir(fnode)) {
		int n_dnodes, n_subdirs;
		i->i_mode |= S_IFDIR;
		i->i_op = &hpfs_dir_iops;
		i->i_fop = &hpfs_dir_ops;
		hpfs_inode->i_parent_dir = le32_to_cpu(fnode->up);
		hpfs_inode->i_dno = le32_to_cpu(fnode->u.external[0].disk_secno);
		if (hpfs_sb(sb)->sb_chk >= 2) {
			struct buffer_head *bh0;
			if (hpfs_map_fnode(sb, hpfs_inode->i_parent_dir, &bh0)) brelse(bh0);
		}
		n_dnodes = 0; n_subdirs = 0;
		hpfs_count_dnodes(i->i_sb, hpfs_inode->i_dno, &n_dnodes, &n_subdirs, NULL);
		i->i_blocks = 4 * n_dnodes;
		i->i_size = 2048 * n_dnodes;
		set_nlink(i, 2 + n_subdirs);
	} else {
		i->i_mode |= S_IFREG;
		if (!hpfs_inode->i_ea_mode) i->i_mode &= ~0111;
		i->i_op = &hpfs_file_iops;
		i->i_fop = &hpfs_file_ops;
		set_nlink(i, 1);
		i->i_size = le32_to_cpu(fnode->file_size);
		i->i_blocks = ((i->i_size + 511) >> 9) + 1;
		i->i_data.a_ops = &hpfs_aops;
		hpfs_i(i)->mmu_private = i->i_size;
	}
	brelse(bh);
}
Example #23
0
static int copy_single_file(const char *from, const char *to)
{
	FILE *from_stream, *to_stream;
	struct stat st;
	char buf[4096];
	size_t len;

	if (check_the_same(from, to)) {
		fprintf(stderr, "%s: '%s' is the same as '%s'\n", __func__, from, to);
		return RecursiveOp_Callback_Error;
	}

	if (lstat(from, &st)) {
		perror("lstat");
		return RecursiveOp_Callback_Error;
	}

	if (S_ISLNK(st.st_mode)) {
		/* symbolic links should be copied in special way */
		char *link_buffer;
		int need_free;
		ssize_t link_len;

		/* get large enough buffer to read link content */
		if (st.st_size < sizeof(buf)) {
			link_buffer = buf;
			need_free = 0;
		}
		else {
			link_buffer = MEM_callocN(st.st_size + 2, "copy_single_file link_buffer");
			need_free = 1;
		}

		link_len = readlink(from, link_buffer, st.st_size + 1);
		if (link_len < 0) {
			perror("readlink");

			if (need_free) MEM_freeN(link_buffer);

			return RecursiveOp_Callback_Error;
		}

		link_buffer[link_len] = 0;

		if (symlink(link_buffer, to)) {
			perror("symlink");
			if (need_free) MEM_freeN(link_buffer);
			return RecursiveOp_Callback_Error;
		}

		if (need_free)
			MEM_freeN(link_buffer);

		return RecursiveOp_Callback_OK;
	}
	else if (S_ISCHR(st.st_mode) ||
	         S_ISBLK(st.st_mode) ||
	         S_ISFIFO(st.st_mode) ||
	         S_ISSOCK(st.st_mode))
	{
		/* copy special type of file */
		if (mknod(to, st.st_mode, st.st_rdev)) {
			perror("mknod");
			return RecursiveOp_Callback_Error;
		}

		if (set_permissions(to, &st))
			return RecursiveOp_Callback_Error;

		return RecursiveOp_Callback_OK;
	}
	else if (!S_ISREG(st.st_mode)) {
		fprintf(stderr, "Copying of this kind of files isn't supported yet\n");
		return RecursiveOp_Callback_Error;
	}

	from_stream = fopen(from, "rb");
	if (!from_stream) {
		perror("fopen");
		return RecursiveOp_Callback_Error;
	}

	to_stream = fopen(to, "wb");
	if (!to_stream) {
		perror("fopen");
		fclose(from_stream);
		return RecursiveOp_Callback_Error;
	}

	while ((len = fread(buf, 1, sizeof(buf), from_stream)) > 0) {
		fwrite(buf, 1, len, to_stream);
	}

	fclose(to_stream);
	fclose(from_stream);

	if (set_permissions(to, &st))
		return RecursiveOp_Callback_Error;

	return RecursiveOp_Callback_OK;
}
Example #24
0
static void analyze_file(const char *filename)
{
  int fd, filekind;
  u8 filesize;
  struct stat sb;
  char *reason;
  SOURCE *s;

  print_line(0, "--- %s", filename);

  /* stat check */
  if (stat(filename, &sb) < 0) {
    errore("Can't stat %.300s", filename);
    return;
  }

  filekind = 0;
  filesize = 0;
  reason = NULL;
  if (S_ISREG(sb.st_mode)) {
    filesize = sb.st_size;
    print_kind(filekind, filesize, 1);
  } else if (S_ISBLK(sb.st_mode))
    filekind = 1;
  else if (S_ISCHR(sb.st_mode))
    filekind = 2;
  else if (S_ISDIR(sb.st_mode))
    reason = "Is a directory";
  else if (S_ISFIFO(sb.st_mode))
    reason = "Is a FIFO";
#ifdef S_ISSOCK
  else if (S_ISSOCK(sb.st_mode))
    reason = "Is a socket";
#endif
  else
    reason = "Is an unknown kind of special file";

  if (reason != NULL) {
    error("%.300s: %s", filename, reason);
    return;
  }

  /* Mac OS type & creator code (if running on Mac OS X) */
#ifdef USE_MACOS_TYPE
  if (filekind == 0)
    show_macos_type(filename);
#endif

  /* empty regular files need no further analysis */
  if (filekind == 0 && filesize == 0)
    return;

  /* open for reading */
  fd = open(filename, O_RDONLY);
  if (fd < 0) {
    errore("Can't open %.300s", filename);
    return;
  }

  /* (try to) guard against TTY character devices */
  if (filekind == 2) {
    if (isatty(fd)) {
      error("%.300s: Is a TTY device", filename);
      return;
    }
  }

  /* create a source */
  s = init_file_source(fd, filekind);

  /* tell the user what it is */
  if (filekind != 0)
    print_kind(filekind, s->size, s->size_known);

  /* now analyze it */
  analyze_source(s, 0);

  /* finish it up */
  close_source(s);
}
Example #25
0
int default_init()
{
	struct stat s;
	int i;

	/* FIXME: other modules might need this, too */
	rec_buffer_init();
	send_buffer_init();

	if (stat(drv.device, &s) == -1) {
		logprintf(LIRC_ERROR, "could not get file information for %s", drv.device);
		logperror(LIRC_ERROR, "default_init()");
		return (0);
	}

	/* file could be unix socket, fifo and native lirc device */
	if (S_ISSOCK(s.st_mode)) {
		struct sockaddr_un addr;
		addr.sun_family = AF_UNIX;
		strncpy(addr.sun_path, drv.device, sizeof(addr.sun_path) - 1);

		drv.fd = socket(AF_UNIX, SOCK_STREAM, 0);
		if (drv.fd == -1) {
			logprintf(LIRC_ERROR, "could not create socket");
			logperror(LIRC_ERROR, "default_init()");
			return (0);
		}

		if (connect(drv.fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
			logprintf(LIRC_ERROR, "could not connect to unix socket %s", drv.device);
			logperror(LIRC_ERROR, "default_init()");
			default_deinit();
			close(drv.fd);
			return (0);
		}

		logprintf(LIRC_TRACE, "using unix socket lirc device");
		drv.features = LIRC_CAN_REC_MODE2 | LIRC_CAN_SEND_PULSE;
		drv.rec_mode = LIRC_MODE_MODE2;	/* this might change in future */
		drv.send_mode = LIRC_MODE_PULSE;
		return (1);
	}

	if ((drv.fd = open(drv.device, O_RDWR)) < 0) {
		logprintf(LIRC_ERROR, "could not open %s", drv.device);
		logperror(LIRC_ERROR, "default_init()");
		return (0);
	}
	if (S_ISFIFO(s.st_mode)) {
		logprintf(LIRC_TRACE, "using defaults for the Irman");
		drv.features = LIRC_CAN_REC_MODE2;
		drv.rec_mode = LIRC_MODE_MODE2;	/* this might change in future */
		return (1);
	} else if (!S_ISCHR(s.st_mode)) {
		default_deinit();
		logprintf(LIRC_ERROR, "%s is not a character device!!!", drv.device);
		logperror(LIRC_ERROR, "something went wrong during installation");
		return (0);
	} else if (default_ioctl(LIRC_GET_FEATURES, &drv.features) == -1) {
		logprintf(LIRC_ERROR, "could not get hardware features");
		logprintf(LIRC_ERROR, "this device driver does not support the LIRC ioctl interface");
		if (major(s.st_rdev) == 13) {
			logprintf(LIRC_ERROR, "did you mean to use the devinput driver instead of the %s driver?",
				  drv.name);
		} else {
			logprintf(LIRC_ERROR, "major number of %s is %lu", drv.device, (__u32) major(s.st_rdev));
			logprintf(LIRC_ERROR, "make sure %s is a LIRC device and use a current version of the driver",
				  drv.device);
		}
		default_deinit();
		return (0);
	}
	else {
		if (!(LIRC_CAN_SEND(drv.features) || LIRC_CAN_REC(drv.features))) {
			logprintf(LIRC_TRACE, "driver supports neither sending nor receiving of IR signals");
		}
		if (LIRC_CAN_SEND(drv.features) && LIRC_CAN_REC(drv.features)) {
			logprintf(LIRC_TRACE, "driver supports both sending and receiving");
		} else if (LIRC_CAN_SEND(drv.features)) {
			logprintf(LIRC_TRACE, "driver supports sending");
		} else if (LIRC_CAN_REC(drv.features)) {
			logprintf(LIRC_TRACE, "driver supports receiving");
		}
	}

	/* set send/receive method */
	drv.send_mode = 0;
	if (LIRC_CAN_SEND(drv.features)) {
		for (i = 0; supported_send_modes[i] != 0; i++) {
			if (LIRC_CAN_SEND(drv.features) == supported_send_modes[i]) {
				drv.send_mode = LIRC_SEND2MODE(supported_send_modes[i]);
				break;
			}
		}
		if (supported_send_modes[i] == 0) {
			logprintf(LIRC_NOTICE, "the send method of the driver is not yet supported by lircd");
		}
	}
	drv.rec_mode = 0;
	if (LIRC_CAN_REC(drv.features)) {
		for (i = 0; supported_rec_modes[i] != 0; i++) {
			if (LIRC_CAN_REC(drv.features) == supported_rec_modes[i]) {
				drv.rec_mode = LIRC_REC2MODE(supported_rec_modes[i]);
				break;
			}
		}
		if (supported_rec_modes[i] == 0) {
			logprintf(LIRC_NOTICE, "the receive method of the driver is not yet supported by lircd");
		}
	}
	if (drv.rec_mode == LIRC_MODE_MODE2) {
		/* get resolution */
		drv.resolution = 0;
		if ((drv.features & LIRC_CAN_GET_REC_RESOLUTION)
		    && (default_ioctl(LIRC_GET_REC_RESOLUTION, &drv.resolution) != -1)) {
			logprintf(LIRC_TRACE, "resolution of receiver: %d", drv.resolution);
		}

	} else if (drv.rec_mode == LIRC_MODE_LIRCCODE) {
		if (default_ioctl(LIRC_GET_LENGTH,
                                  (void*) &drv.code_length) == -1) {
			logprintf(LIRC_ERROR, "could not get code length");
			logperror(LIRC_ERROR, "default_init()");
			default_deinit();
			return (0);
		}
		if (drv.code_length > sizeof(ir_code) * CHAR_BIT) {
			logprintf(LIRC_ERROR, "lircd can not handle %lu bit codes", drv.code_length);
			default_deinit();
			return (0);
		}
	}
	if (!(drv.send_mode || drv.rec_mode)) {
		default_deinit();
		return (0);
	}
	return (1);
}
Example #26
0
bool vfopen (char const *filename) 

{
	struct stat loadstat;
	struct stat savestat;
	char loadname [FILENAME_MAX];
	char savename [FILENAME_MAX];
	unsigned bailout = 0;
	unsigned version = 0;
	unsigned maximum = 0;
	char *extender;
	makepath (loadname, getenv ("PWD"), filename);
	makepath (savename, getenv ("PWD"), filename);
	if (lstat (loadname, &loadstat)) 
	{
		error (bailout, errno, "Can't open %s", loadname);
		return (false);
	}
	if (S_ISDIR (loadstat.st_mode)) 
	{
		error (bailout, 0, "Won't open %s: file is a folder", loadname);
		return (false);
	}
	if (S_ISLNK (loadstat.st_mode)) 
	{
		error (bailout, 0, "Won't open %s: file is a symlink", loadname);
		return (false);
	}
	if (S_ISBLK (loadstat.st_mode)) 
	{
		error (bailout, 0, "Won't open %s: file is a device", loadname);
		return (false);
	}
	if (S_ISCHR (loadstat.st_mode)) 
	{
		error (bailout, 0, "Won't open %s: file is a device", loadname);
		return (false);
	}
	if (S_ISFIFO (loadstat.st_mode)) 
	{
		error (bailout, 0, "Won't open %s: file is a fifo", loadname);
		return (false);
	}
	if (S_ISSOCK (loadstat.st_mode)) 
	{
		error (bailout, 0, "Won't open %s: file is a socket", loadname);
		return (false);
	}
	for (version = FILE_VER_MAX; version > 0; version /= 10) 
	{
		maximum++;
	}
	for (extender = savename; *extender; extender++);
	*extender++ = FILE_C_EXTENDER;
	for (version = 1; version < FILE_VER_MAX; version++) 
	{
		unsigned value = version;
		unsigned digit = maximum;
		for (extender [digit] = (char) (0); digit-- > 0; value /= 10) 
		{
			extender [digit] = (value % 10) + '0';
		}
		if (lstat (savename, &savestat)) 
		{
			if (!freopen (loadname, "rb", stdin)) 
			{
				error (bailout, errno, "Can't open %s for input", loadname);
				return (false);
			}
			if (rename (loadname, savename)) 
			{
				error (bailout, errno, "Can't rename %s as %s", loadname, savename);
				return (false);
			}
			if (!freopen (loadname, "wb", stdout)) 
			{
				error (bailout, errno, "Can't open %s for output", loadname);
				return (false);
			}
			if (chmod (loadname, loadstat.st_mode)) 
			{
				error (bailout, errno, "Can't preserve %s permissions", loadname);
				return (false);
			}
			if (chown (loadname, loadstat.st_uid, loadstat.st_gid)) 
			{
				error (bailout, errno, "Can't preserve %s ownership", loadname);
				return (false);
			}
			return (true);
		}
	}
	error (bailout, 0, "Won't open %s: Too many file versions", loadname);
	return (false);
}
Example #27
0
struct super_block *
ncp_read_super(struct super_block *sb, void *raw_data, int silent)
{
	struct ncp_mount_data *data = (struct ncp_mount_data *) raw_data;
	struct ncp_server *server;
	struct file *ncp_filp;
	struct inode *root_inode;
	kdev_t dev = sb->s_dev;
	int error;
#ifdef CONFIG_NCPFS_PACKET_SIGNING
	int options;
#endif
	struct ncpfs_inode_info finfo;

	MOD_INC_USE_COUNT;
	if (data == NULL)
		goto out_no_data;
	if (data->version != NCP_MOUNT_VERSION)
		goto out_bad_mount;
	ncp_filp = fget(data->ncp_fd);
	if (!ncp_filp)
		goto out_bad_file;
	if (!S_ISSOCK(ncp_filp->f_dentry->d_inode->i_mode))
		goto out_bad_file2;

	lock_super(sb);

	sb->s_blocksize = 1024;	/* Eh...  Is this correct? */
	sb->s_blocksize_bits = 10;
	sb->s_magic = NCP_SUPER_MAGIC;
	sb->s_dev = dev;
	sb->s_op = &ncp_sops;

	/* We must malloc our own super-block info */
	server = (struct ncp_server *) ncp_kmalloc(sizeof(struct ncp_server),
						   GFP_KERNEL);
	if (server == NULL)
		goto out_no_server;
	NCP_SBP(sb) = server;

	server->ncp_filp = ncp_filp;
	server->lock = 0;
	server->wait = NULL;
	server->packet = NULL;
	server->buffer_size = 0;
	server->conn_status = 0;
	server->root_dentry = NULL;
	server->root_setuped = 0;
#ifdef CONFIG_NCPFS_PACKET_SIGNING
	server->sign_wanted = 0;
	server->sign_active = 0;
#endif
	server->auth.auth_type = NCP_AUTH_NONE;
	server->auth.object_name_len = 0;
	server->auth.object_name = NULL;
	server->auth.object_type = 0;
	server->priv.len = 0;
	server->priv.data = NULL;

	server->m = *data;
	/* Althought anything producing this is buggy, it happens
	   now because of PATH_MAX changes.. */
	if (server->m.time_out < 10) {
		server->m.time_out = 10;
		printk(KERN_INFO "You need to recompile your ncpfs utils..\n");
	}
	server->m.file_mode = (server->m.file_mode &
			       (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFREG;
	server->m.dir_mode = (server->m.dir_mode &
			      (S_IRWXU | S_IRWXG | S_IRWXO)) | S_IFDIR;

	server->packet_size = NCP_PACKET_SIZE;
	server->packet = ncp_kmalloc(NCP_PACKET_SIZE, GFP_KERNEL);
	if (server->packet == NULL)
		goto out_no_packet;

	ncp_lock_server(server);
	error = ncp_connect(server);
	ncp_unlock_server(server);
	if (error < 0)
		goto out_no_connect;
	DPRINTK(KERN_DEBUG "ncp_read_super: NCP_SBP(sb) = %x\n", (int) NCP_SBP(sb));

#ifdef CONFIG_NCPFS_PACKET_SIGNING
	if (ncp_negotiate_size_and_options(server, NCP_DEFAULT_BUFSIZE,
		NCP_DEFAULT_OPTIONS, &(server->buffer_size), &options) == 0)
	{
		if (options != NCP_DEFAULT_OPTIONS)
		{
			if (ncp_negotiate_size_and_options(server, 
				NCP_DEFAULT_BUFSIZE,
				options & 2, 
				&(server->buffer_size), &options) != 0)
				
			{
				goto out_no_bufsize;
			}
		}
		if (options & 2)
			server->sign_wanted = 1;
	}
	else 
#endif	/* CONFIG_NCPFS_PACKET_SIGNING */
	if (ncp_negotiate_buffersize(server, NCP_DEFAULT_BUFSIZE,
  				     &(server->buffer_size)) != 0)
		goto out_no_bufsize;
	DPRINTK(KERN_DEBUG "ncpfs: bufsize = %d\n", server->buffer_size);

	ncp_init_root(server, &finfo);
	server->name_space[finfo.nw_info.i.volNumber] = NW_NS_DOS;
        root_inode = ncp_iget(sb, &finfo);
        if (!root_inode)
		goto out_no_root;
	DPRINTK(KERN_DEBUG "ncp_read_super: root vol=%d\n", NCP_FINFO(root_inode)->volNumber);
        server->root_dentry = sb->s_root = d_alloc_root(root_inode, NULL);
        if (!sb->s_root)
		goto out_no_root;
	server->root_dentry->d_op = &ncp_dentry_operations;
	unlock_super(sb);
	return sb;

out_no_root:
	printk(KERN_ERR "ncp_read_super: get root inode failed\n");
	iput(root_inode);
	goto out_disconnect;
out_no_bufsize:
	printk(KERN_ERR "ncp_read_super: could not get bufsize\n");
out_disconnect:
	ncp_lock_server(server);
	ncp_disconnect(server);
	ncp_unlock_server(server);
	goto out_free_packet;
out_no_connect:
	printk(KERN_ERR "ncp_read_super: Failed connection, error=%d\n", error);
out_free_packet:
	ncp_kfree_s(server->packet, server->packet_size);
	goto out_free_server;
out_no_packet:
	printk(KERN_ERR "ncp_read_super: could not alloc packet\n");
out_free_server:
	ncp_kfree_s(NCP_SBP(sb), sizeof(struct ncp_server));
	goto out_unlock;
out_no_server:
	printk(KERN_ERR "ncp_read_super: could not alloc ncp_server\n");
out_unlock:
	/* 23/12/1998 Marcin Dalecki <*****@*****.**>:
	 * 
	 * The previously used put_filp(ncp_filp); was bogous, since
	 * it doesn't proper unlocking.
	 */
	fput(ncp_filp);
	unlock_super(sb);
	goto out;

out_bad_file2:
	fput(ncp_filp);
out_bad_file:
	printk(KERN_ERR "ncp_read_super: invalid ncp socket\n");
	goto out;
out_bad_mount:
	printk(KERN_INFO "ncp_read_super: kernel requires mount version %d\n",
		NCP_MOUNT_VERSION);
	goto out;
out_no_data:
	printk(KERN_ERR "ncp_read_super: missing data argument\n");
out:
	sb->s_dev = 0;
	MOD_DEC_USE_COUNT;
	return NULL;
}
Example #28
0
bool Entry::is_socket()
{
    return S_ISSOCK(archive_entry_filetype(_entry));
}
Example #29
0
isc_result_t
isc_entropy_createfilesource(isc_entropy_t *ent, const char *fname) {
	int fd;
	struct stat _stat;
	isc_boolean_t is_usocket = ISC_FALSE;
	isc_boolean_t is_connected = ISC_FALSE;
	isc_result_t ret;
	isc_entropysource_t *source;

	REQUIRE(VALID_ENTROPY(ent));
	REQUIRE(fname != NULL);

	LOCK(&ent->lock);

	if (stat(fname, &_stat) < 0) {
		ret = isc__errno2result(errno);
		goto errout;
	}
	/*
	 * Solaris 2.5.1 does not have support for sockets (S_IFSOCK),
	 * but it does return type S_IFIFO (the OS believes that
	 * the socket is a fifo).  This may be an issue if we tell
	 * the program to look at an actual FIFO as its source of
	 * entropy.
	 */
#if defined(S_ISSOCK)
	if (S_ISSOCK(_stat.st_mode))
		is_usocket = ISC_TRUE;
#endif
#if defined(S_ISFIFO) && defined(sun)
	if (S_ISFIFO(_stat.st_mode))
		is_usocket = ISC_TRUE;
#endif
	if (is_usocket)
		fd = socket(PF_UNIX, SOCK_STREAM, 0);
	else
		fd = open(fname, O_RDONLY | PORT_NONBLOCK, 0);

	if (fd < 0) {
		ret = isc__errno2result(errno);
		goto errout;
	}

	ret = make_nonblock(fd);
	if (ret != ISC_R_SUCCESS)
		goto closefd;

	if (is_usocket) {
		struct sockaddr_un sname;

		memset(&sname, 0, sizeof(sname));
		sname.sun_family = AF_UNIX;
		strlcpy(sname.sun_path, fname, sizeof(sname.sun_path));
#ifdef ISC_PLATFORM_HAVESALEN
#if !defined(SUN_LEN)
#define SUN_LEN(su) \
	(sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
#endif
		sname.sun_len = SUN_LEN(&sname);
#endif

		if (connect(fd, (struct sockaddr *) &sname,
			    sizeof(struct sockaddr_un)) < 0) {
			if (errno != EINPROGRESS) {
				ret = isc__errno2result(errno);
				goto closefd;
			}
		} else
			is_connected = ISC_TRUE;
	}

	source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
	if (source == NULL) {
		ret = ISC_R_NOMEMORY;
		goto closefd;
	}

	/*
	 * From here down, no failures can occur.
	 */
	source->magic = SOURCE_MAGIC;
	source->ent = ent;
	source->total = 0;
	source->bad = ISC_FALSE;
	memset(source->name, 0, sizeof(source->name));
	ISC_LINK_INIT(source, link);
	if (is_usocket) {
		source->sources.usocket.handle = fd;
		if (is_connected)
			source->sources.usocket.status =
					isc_usocketsource_connected;
		else
			source->sources.usocket.status =
					isc_usocketsource_connecting;
		source->sources.usocket.sz_to_recv = 0;
		source->type = ENTROPY_SOURCETYPE_USOCKET;
	} else {
		source->sources.file.handle = fd;
		source->type = ENTROPY_SOURCETYPE_FILE;
	}

	/*
	 * Hook it into the entropy system.
	 */
	ISC_LIST_APPEND(ent->sources, source, link);
	ent->nsources++;

	UNLOCK(&ent->lock);
	return (ISC_R_SUCCESS);

 closefd:
	(void)close(fd);

 errout:
	UNLOCK(&ent->lock);

	return (ret);
}
Example #30
0
void getDirFileInfo(char dirname[])
{
    DIR *dir;
    struct dirent *dirent;
    int i = 0;
    struct stat *buf;
    struct passwd *usr;
    struct group *grp;
    char filename[80] = {0};
    
    buf = (struct stat *)malloc(sizeof(struct stat));

    if((dir = opendir(dirname)) == NULL)
    {
        my_err("opendir", __LINE__);
    }



    while((dirent = readdir(dir)) != NULL)
    {
        strcpy(filename, dirname);
        strcat(filename, "/");
        strcat(filename, dirent->d_name);


        lstat(filename, buf);                  //用lstat避免奇奇怪怪的错误

        //获取文件类型
        if(S_ISLNK(buf->st_mode))
        {
            fileinfo[i].type = 'l';
        }
        else if(S_ISREG(buf->st_mode)) 
        {
            fileinfo[i].type = '-';
        }
        else if(S_ISDIR(buf->st_mode))
        {
            fileinfo[i].type = 'd';
        }
        else if(S_ISCHR(buf->st_mode))
        {
            fileinfo[i].type = 'c';
        }
        else if(S_ISBLK(buf->st_mode))
        {
            fileinfo[i].type = 'b';
        }
        else if(S_ISFIFO(buf->st_mode))
        {
            fileinfo[i].type = 'f';
        }
        else if(S_ISSOCK(buf->st_mode))
        {
            fileinfo[i].type = 's';
        }

        //获取文件权限
        fileinfo[i].mode[0] = (buf->st_mode & S_IRUSR) ? 'r' : '-';
        fileinfo[i].mode[1] = (buf->st_mode & S_IWUSR) ? 'w' : '-';
        fileinfo[i].mode[2] = (buf->st_mode & S_IXUSR) ? 'x' : '-';
        fileinfo[i].mode[3] = (buf->st_mode & S_IRGRP) ? 'r' : '-';
        fileinfo[i].mode[4] = (buf->st_mode & S_IWGRP) ? 'w' : '-';
        fileinfo[i].mode[5] = (buf->st_mode & S_IXGRP) ? 'x' : '-';
        fileinfo[i].mode[6] = (buf->st_mode & S_IROTH) ? 'r' : '-';
        fileinfo[i].mode[7] = (buf->st_mode & S_IWOTH) ? 'w' : '-';
        fileinfo[i].mode[8] = (buf->st_mode & S_IXOTH) ? 'x' : '-';

        printf("%s\n", fileinfo[i].mode);

        //获取文件硬链接的个数
        fileinfo[i].number = buf->st_nlink;
        
        //获取文件的所有者
        usr = getpwuid(buf->st_uid);
        strcpy(fileinfo[i].uid, usr->pw_name);

        //获取文件所有者的所属组
        grp = getgrgid(buf->st_gid);
        strcpy(fileinfo[i].gid, grp->gr_name);

        //获取文件的大小
        fileinfo[i].size = buf->st_size;

        //获取文件最后更改的时间
        fileinfo[i].mtime = buf->st_mtime;

        //获取文件的文件名
        strcpy(fileinfo[i].filename, dirent->d_name);
        
        i++;
    }
}