Beispiel #1
0
/* Copy files from source_dir to fs */
static errcode_t __populate_fs(ext2_filsys fs, ext2_ino_t parent_ino,
			       const char *source_dir, ext2_ino_t root,
			       struct hdlinks_s *hdlinks)
{
	const char	*name;
	DIR		*dh;
	struct dirent	*dent;
	struct stat	st;
	char		ln_target[PATH_MAX];
	unsigned int	save_inode;
	ext2_ino_t	ino;
	errcode_t	retval;
	int		read_cnt;
	int		hdlink;

	if (chdir(source_dir) < 0) {
		com_err(__func__, errno,
			_("while changing working directory to \"%s\""),
			source_dir);
		return errno;
	}

	if (!(dh = opendir("."))) {
		com_err(__func__, errno,
			_("while opening directory \"%s\""), source_dir);
		return errno;
	}

	while ((dent = readdir(dh))) {
		if ((!strcmp(dent->d_name, ".")) ||
		    (!strcmp(dent->d_name, "..")))
			continue;
		lstat(dent->d_name, &st);
		name = dent->d_name;

		/* Check for hardlinks */
		save_inode = 0;
		if (!S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode) &&
		    st.st_nlink > 1) {
			hdlink = is_hardlink(hdlinks, st.st_dev, st.st_ino);
			if (hdlink >= 0) {
				retval = add_link(fs, parent_ino,
						  hdlinks->hdl[hdlink].dst_ino,
						  name);
				if (retval) {
					com_err(__func__, retval,
						"while linking %s", name);
					return retval;
				}
				continue;
			} else
				save_inode = 1;
		}

		switch(st.st_mode & S_IFMT) {
		case S_IFCHR:
		case S_IFBLK:
		case S_IFIFO:
			retval = do_mknod_internal(fs, parent_ino, name, &st);
			if (retval) {
				com_err(__func__, retval,
					_("while creating special file "
					  "\"%s\""), name);
				return retval;
			}
			break;
		case S_IFSOCK:
			/* FIXME: there is no make socket function atm. */
			com_err(__func__, 0,
				_("ignoring socket file \"%s\""), name);
			continue;
		case S_IFLNK:
			read_cnt = readlink(name, ln_target,
					    sizeof(ln_target));
			if (read_cnt == -1) {
				com_err(__func__, errno,
					_("while trying to readlink \"%s\""),
					name);
				return errno;
			}
			ln_target[read_cnt] = '\0';
			retval = do_symlink_internal(fs, parent_ino, name,
						     ln_target, root);
			if (retval) {
				com_err(__func__, retval,
					_("while writing symlink\"%s\""),
					name);
				return retval;
			}
			break;
		case S_IFREG:
			retval = do_write_internal(fs, parent_ino, name, name,
						   root);
			if (retval) {
				com_err(__func__, retval,
					_("while writing file \"%s\""), name);
				return retval;
			}
			break;
		case S_IFDIR:
			retval = do_mkdir_internal(fs, parent_ino, name, &st,
						   root);
			if (retval) {
				com_err(__func__, retval,
					_("while making dir \"%s\""), name);
				return retval;
			}
			retval = ext2fs_namei(fs, root, parent_ino,
					      name, &ino);
			if (retval) {
				com_err(name, retval, 0);
					return retval;
			}
			/* Populate the dir recursively*/
			retval = __populate_fs(fs, ino, name, root, hdlinks);
			if (retval) {
				com_err(__func__, retval,
					_("while adding dir \"%s\""), name);
				return retval;
			}
			if (chdir("..")) {
				com_err(__func__, errno,
					_("during cd .."));
				return errno;
			}
			break;
		default:
			com_err(__func__, 0,
				_("ignoring entry \"%s\""), name);
		}

		retval =  ext2fs_namei(fs, root, parent_ino, name, &ino);
		if (retval) {
			com_err(name, retval, 0);
			return retval;
		}

		retval = set_inode_extra(fs, parent_ino, ino, &st);
		if (retval) {
			com_err(__func__, retval,
				_("while setting inode for \"%s\""), name);
			return retval;
		}

		/* Save the hardlink ino */
		if (save_inode) {
			/*
			 * Check whether need more memory, and we don't need
			 * free() since the lifespan will be over after the fs
			 * populated.
			 */
			if (hdlinks->count == hdlinks->size) {
				void *p = realloc(hdlinks->hdl,
						(hdlinks->size + HDLINK_CNT) *
						sizeof(struct hdlink_s));
				if (p == NULL) {
					com_err(name, errno,
						_("Not enough memory"));
					return errno;
				}
				hdlinks->hdl = p;
				hdlinks->size += HDLINK_CNT;
			}
			hdlinks->hdl[hdlinks->count].src_dev = st.st_dev;
			hdlinks->hdl[hdlinks->count].src_ino = st.st_ino;
			hdlinks->hdl[hdlinks->count].dst_ino = ino;
			hdlinks->count++;
		}
	}
	closedir(dh);
	return retval;
}
Beispiel #2
0
int processdir(int level, const char *base, const char *dirname, struct stat *sb,
	struct filenode *dir, struct filenode *root, int curroffset)
{
	DIR *dirfd;
	struct dirent *dp;
	struct filenode *n, *link;
	struct excludes *pe;

	if (level <= 1) {
		/* Ok, to make sure . and .. are handled correctly
		 * we add them first.  Note also that we alloc them
		 * first to get to know the real name
		 */
		link = newnode(base, ".", curroffset);
		if (!lstat(link->realname, sb)) {
			setnode(link, sb->st_dev, sb->st_ino, sb->st_mode);
			append(&dir->dirlist, link);

			/* special case for root node - '..'s in subdirs should link to
			 *   '.' of root node, not root node itself.
			 */
			dir->dirlist.owner = link;

			curroffset = alignnode(link, curroffset, 0) + spaceneeded(link);
			n = newnode(base, "..", curroffset);

			if (!lstat(n->realname, sb)) {
				setnode(n, sb->st_dev, sb->st_ino, sb->st_mode);
				append(&dir->dirlist, n);
				n->orig_link = link;
				curroffset = alignnode(n, curroffset, 0) + spaceneeded(n);
			}
		}
	}

	dirfd = opendir(dir->realname);
	while((dp = readdir(dirfd))) {
		/* don't process main . and .. twice */
		if (level <= 1 &&
		    (strcmp(dp->d_name, ".") == 0
		     || strcmp(dp->d_name, "..") == 0))
			continue;
		n = newnode(base, dp->d_name, curroffset);

		/* Process exclude list. */
		for (pe = excludelist; pe; pe = pe->next) {
			if (!nodematch(pe->pattern, n)) { freenode(n); break; }
		}
		if (pe) continue;

		if (lstat(n->realname, sb)) {
			fprintf(stderr, "ignoring '%s' (lstat failed)\n", n->realname);
			freenode(n); continue;
		}

		/* Handle special names */
		if ( n->name[0] == '@' ) {
			if (S_ISLNK(sb->st_mode)) {
				/* this is a link to follow at build time */
				n->name = n->name + 1; /* strip off the leading @ */
				memset(bigbuf, 0, sizeof(bigbuf));
				readlink(n->realname, bigbuf, sizeof(bigbuf));
				n->realname = strdup(bigbuf);

				if (lstat(n->realname, sb)) {
					fprintf(stderr, "ignoring '%s' (lstat failed)\n",
						n->realname);
					freenode(n); continue;
				}
			} else if (S_ISREG(sb->st_mode) && sb->st_size == 0) {
				/*
				 *        special file @name,[bcp..],major,minor
				 */
				char      devname[32];
				char      type;
				int       major;
				int       minor;
						
				if (sscanf(n->name, "@%[a-zA-Z0-9],%c,%d,%d",
					   devname, &type, &major, &minor) == 4 ) {
					strcpy(n->name, devname);
					sb->st_rdev = makedev(major, minor);
					sb->st_mode &= ~S_IFMT;
					switch (type) {
					case 'c':
					case 'u':
						sb->st_mode |= S_IFCHR;
						break;
					case 'b':
						sb->st_mode |= S_IFBLK;
						break;
					case 'p':
						sb->st_mode |= S_IFIFO;
						break;
					default:
						fprintf(stderr, "Invalid special device type '%c' "
							"for file %s\n", type, n->realname);
						freenode(n);
						continue;
					}
				}
			}
		}

		setnode(n, sb->st_dev, sb->st_ino, sb->st_mode);
		/* Skip unreadable files/dirs */
		if (!S_ISLNK(n->modes) && access(n->realname, R_OK)) {
			fprintf(stderr, "ignoring '%s' (access failed)\n", n->realname);
			freenode(n); continue;
		}

		/* Look up old links */
		if ( strcmp(n->name, ".") == 0 ) {
			append(&dir->dirlist, n);
			link = n->parent;
		} else if (strcmp(n->name, "..") == 0) {
			append(&dir->dirlist, n);
			link = n->parent->parent;
		} else {
			link = findnode(root, n->ondev, n->onino);
			append(&dir->dirlist, n);
		}

		if (link) {
			n->orig_link = link;
			curroffset = alignnode(n, curroffset, 0) + spaceneeded(n);
			continue;
		}
		if (S_ISREG(sb->st_mode)) {
			curroffset = alignnode(n, curroffset, spaceneeded(n));
			n->size = sb->st_size;
		} else
			curroffset = alignnode(n, curroffset, 0);
		if (S_ISLNK(sb->st_mode)) {
			n->size = sb->st_size;
		}
		curroffset += spaceneeded(n);
		if (S_ISCHR(sb->st_mode) || S_ISBLK(sb->st_mode)) {
			n->devnode = sb->st_rdev;
		}

		if (S_ISDIR(sb->st_mode)) {
			if (!strcmp(n->name, "..")) {
				curroffset = processdir(level+1, dir->realname, dp->d_name,
							sb, dir, root, curroffset);
			} else {
				curroffset = processdir(level+1, n->realname, dp->d_name,
							sb, n, root, curroffset);
			}
		}
	}
	closedir(dirfd);
	return curroffset;
}
Beispiel #3
0
int daemon_listen(DRIVER_CTX *DTX) {
  struct sockaddr_in local_addr, remote_addr;
  THREAD_CTX *TTX = NULL;
  fd_set master, read_fds;
  pthread_attr_t attr;
  struct timeval tv;
  int fdmax, yes = 1;
  int domain = 0;		/* listening on domain socket? */
  int listener;			/* listener fd */
  int i;
  int port = 24, queue = 32;	/* default port and queue size */

  signal(SIGPIPE, SIG_IGN);
  signal(SIGINT,  process_signal);
  signal(SIGTERM, process_signal);
  signal(SIGHUP,  process_signal);

  if (_ds_read_attribute(agent_config, "ServerPort"))
    port = atoi(_ds_read_attribute(agent_config, "ServerPort"));

  if (_ds_read_attribute(agent_config, "ServerQueueSize"))
    queue = atoi(_ds_read_attribute(agent_config, "ServerQueueSize"));

  if (_ds_read_attribute(agent_config, "ServerDomainSocketPath"))
    domain = 1;

  /* initialize */

  FD_ZERO(&master);
  FD_ZERO(&read_fds);

  pthread_attr_init(&attr);
  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

  /* Bind (domain socket) */

  if (domain) {
    struct sockaddr_un saun;
    char *address = strdup(_ds_read_attribute(agent_config, "ServerDomainSocketPath"));
    mode_t mask;
    int len;

    mask = umask (000);

    if (_ds_match_attribute(agent_config, "ServerDomainSymlink", "on")) {
      /* treat ServerDomainSymlink as a symlink path */
      char* old_address = address;
      address = malloc(sizeof(char) * (strlen(address) + 8));
      sprintf(address, "%s.%d", old_address, getpid());
      free(old_address);
      /* address now points to the actual socket, ending in pid */
    }

    listener = socket(AF_UNIX, SOCK_STREAM, 0);
    if (listener == -1) {
      LOG(LOG_CRIT, ERR_DAEMON_SOCKET, strerror(errno));
      umask (mask);
      return(EFAILURE);
    }

    memset(&saun, 0, sizeof(struct sockaddr_un));
    saun.sun_family = AF_UNIX;
    strcpy(saun.sun_path, address);

    unlink(address);
    len = sizeof(saun.sun_family) + strlen(saun.sun_path) + 1;

    LOGDEBUG(INFO_DAEMON_DOMAINSOCK, address);
  
    if (bind(listener, (struct sockaddr *) &saun, len)<0) {
      close(listener);
      LOG(LOG_CRIT, INFO_DAEMON_DOMAINSOCK, address, strerror(errno));
      umask (mask);
      return EFAILURE;
    }    

    if (_ds_match_attribute(agent_config, "ServerDomainSymlink", "on")) {
      /* install symlink for the domain socket */
      char *link_address = _ds_read_attribute(agent_config, "ServerDomainSocketPath");

      /* to atomically replace the socket symlink, make the symlink elsewhere then move it */
      char* new_link_address = malloc(sizeof(char) * (strlen(link_address) + 4));
      sprintf(new_link_address, "%s.new", link_address);

      symlink(address, new_link_address);
      rename(new_link_address, link_address);

      free(new_link_address);
    }

    umask (mask);

    free(address);

  /* Bind to a TCP socket */

  } else {
    listener = socket(AF_INET, SOCK_STREAM, 0);
    if (listener == -1) {
      LOG(LOG_CRIT, ERR_DAEMON_SOCKET, strerror(errno));
      return(EFAILURE);
    }

    if (setsockopt(listener,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {
      close(listener);
      LOG(LOG_CRIT, ERR_DAEMON_SOCKOPT, "SO_REUSEADDR", strerror(errno));
      return(EFAILURE);
    }

    memset(&local_addr, 0, sizeof(struct sockaddr_in));
    local_addr.sin_family = AF_INET;
    local_addr.sin_port = htons(port);
    local_addr.sin_addr.s_addr = INADDR_ANY;

    LOGDEBUG(INFO_DAEMON_BIND, port);

    if (bind(listener, (struct sockaddr *)&local_addr, 
             sizeof(struct sockaddr)) == -1) 
    {
      close(listener);
      LOG(LOG_CRIT, ERR_DAEMON_BIND, port, strerror(errno));
      return(EFAILURE);
    }
  }

  /* Listen */

  if (listen(listener, queue) == -1) {
    close(listener);
    LOG(LOG_CRIT, ERR_DAEMON_LISTEN, strerror(errno));
    return(EFAILURE);
  }

  FD_SET(listener, &master);
  fdmax = listener;

  /* Process new connections (until death or reload) */

  for(;;) {
    read_fds = master;
    tv.tv_sec = 2;
    tv.tv_usec = 0;

    if (__daemon_run == 0) {
      close(listener);

      char* address = _ds_read_attribute(agent_config, "ServerDomainSocketPath");
      if (address) {
        if (_ds_match_attribute(agent_config, "ServerDomainSymlink", "on")) {
          /* unlink the actual domain socket */
          char* real_address = malloc(sizeof(char) * (strlen(address) + 8));
          sprintf(real_address, "%s.%d", address, getpid());
          unlink (real_address);

          /* remove the symlink only if we still own it */
          char link_target[256];
          int ret = readlink(address, link_target, sizeof(link_target)-1);
          if (ret >= 0) {
            /* readlink doesn't null-terminate */
            link_target[ret] = '\0';
            if (!strcmp(link_target, real_address)) {
              unlink (address);
            }
          }

          free(real_address);
        }
        else
          unlink (address);
      }
      
      return 0; 
    }

    if (select(fdmax+1, &read_fds, NULL, NULL, &tv)>0) {

      /* Process read-ready connections */

      for(i=0;i<=fdmax;i++) {
        if (FD_ISSET(i, &read_fds)) {

          /* Accept new connections */

          if (i == listener) {
            int newfd;
            int addrlen = sizeof(remote_addr);

            if ((newfd = accept(listener, 
                                (struct sockaddr *)&remote_addr, 
                                (socklen_t *) &addrlen)) == -1)
            {
              LOG(LOG_WARNING, ERR_DAEMON_ACCEPT, strerror(errno));
              continue;
#ifdef DEBUG
            } else if (!domain) {
              char buff[32];
              LOGDEBUG("connection id %d from %s.", newfd, 
                       inet_ntoa_r(remote_addr.sin_addr, buff, sizeof(buff)));
#endif
            }
            fcntl(newfd, F_SETFL, O_RDWR);
            setsockopt(newfd,SOL_SOCKET,TCP_NODELAY,&yes,sizeof(int));

            /* 
             * Since processing time varies, each new connection gets its own 
             * thread, so we create a new thread context and send it on its way 
             *
             */

            TTX = calloc(1, sizeof(THREAD_CTX));
            if (TTX == NULL) {
              LOG(LOG_CRIT, ERR_MEM_ALLOC);
              close(newfd);
              continue;
            } else {
              TTX->sockfd = newfd;
              TTX->DTX = DTX;
              memcpy(&TTX->remote_addr, &remote_addr, sizeof(remote_addr));

              increment_thread_count();
              if (pthread_create(&TTX->thread, 
                                 &attr, process_connection, (void *) TTX))
              {
                decrement_thread_count();
                LOG(LOG_CRIT, ERR_DAEMON_THREAD, strerror(errno));
                close(TTX->sockfd);
                free(TTX);
                continue;
              }
            }
          } /* if i == listener */
        } /* if FD_SET else */
      } /* for(i.. */
    }  /* if (select)... */
  } /* for(;;) */

  /* Shutdown - we should never get here, but who knows */

  close(listener);
  pthread_attr_destroy(&attr);
  return 0;
}
Beispiel #4
0
static int
copy_internal (const char *src_path, const char *dst_path,
	       int new_dst,
	       dev_t device,
	       struct dir_list *ancestors,
	       const struct cp_options *x,
	       int command_line_arg,
	       int *copy_into_self,
	       int *rename_succeeded)
{
  struct stat src_sb;
  struct stat dst_sb;
  mode_t src_mode;
  mode_t src_type;
  char *earlier_file = NULL;
  char *dst_backup = NULL;
  int backup_succeeded = 0;
  int delayed_fail;
  int copied_as_regular = 0;
  int ran_chown = 0;
  int preserve_metadata;

  if (x->move_mode && rename_succeeded)
    *rename_succeeded = 0;

  *copy_into_self = 0;
  if ((*(x->xstat)) (src_path, &src_sb))
    {
      error (0, errno, _("cannot stat %s"), quote (src_path));
      return 1;
    }

  src_type = src_sb.st_mode;

  src_mode = src_sb.st_mode;

  if (S_ISDIR (src_type) && !x->recursive)
    {
      error (0, 0, _("omitting directory %s"), quote (src_path));
      return 1;
    }

  /* Detect the case in which the same source file appears more than
     once on the command line and no backup option has been selected.
     If so, simply warn and don't copy it the second time.
     This check is enabled only if x->src_info is non-NULL.  */
  if (command_line_arg)
    {
      if ( ! S_ISDIR (src_sb.st_mode)
	   && x->backup_type == none
	   && seen_file (x->src_info, src_path, &src_sb))
	{
	  error (0, 0, _("warning: source file %s specified more than once"),
		 quote (src_path));
	  return 0;
	}

      record_file (x->src_info, src_path, &src_sb);
    }

  if (!new_dst)
    {
      if ((*(x->xstat)) (dst_path, &dst_sb))
	{
	  if (errno != ENOENT)
	    {
	      error (0, errno, _("cannot stat %s"), quote (dst_path));
	      return 1;
	    }
	  else
	    {
	      new_dst = 1;
	    }
	}
      else
	{
	  int return_now;
	  int ok = same_file_ok (src_path, &src_sb, dst_path, &dst_sb,
				 x, &return_now);
	  if (return_now)
	    return 0;

	  if (! ok)
	    {
	      error (0, 0, _("%s and %s are the same file"),
		     quote_n (0, src_path), quote_n (1, dst_path));
	      return 1;
	    }

	  if (!S_ISDIR (dst_sb.st_mode))
	    {
	      if (S_ISDIR (src_type))
		{
		  error (0, 0,
		     _("cannot overwrite non-directory %s with directory %s"),
			 quote_n (0, dst_path), quote_n (1, src_path));
		  return 1;
		}

	      /* Don't let the user destroy their data, even if they try hard:
		 This mv command must fail (likewise for cp):
		   rm -rf a b c; mkdir a b c; touch a/f b/f; mv a/f b/f c
		 Otherwise, the contents of b/f would be lost.
		 In the case of `cp', b/f would be lost if the user simulated
		 a move using cp and rm.
		 Note that it works fine if you use --backup=numbered.  */
	      if (command_line_arg
		  && x->backup_type != numbered
		  && seen_file (x->dest_info, dst_path, &dst_sb))
		{
		  error (0, 0,
			 _("will not overwrite just-created %s with %s"),
			 quote_n (0, dst_path), quote_n (1, src_path));
		  return 1;
		}
	    }

	  if (!S_ISDIR (src_type))
	    {
	      if (S_ISDIR (dst_sb.st_mode))
		{
		  error (0, 0,
		       _("cannot overwrite directory %s with non-directory"),
			 quote (dst_path));
		  return 1;
		}

	      if (x->update && MTIME_CMP (src_sb, dst_sb) <= 0)
		{
		  /* We're using --update and the source file is older
		     than the destination file, so there is no need to
		     copy or move.  */
		  /* Pretend the rename succeeded, so the caller (mv)
		     doesn't end up removing the source file.  */
		  if (rename_succeeded)
		    *rename_succeeded = 1;
		  return 0;
		}
	    }

	  /* When there is an existing destination file, we may end up
	     returning early, and hence not copying/moving the file.
	     This may be due to an interactive `negative' reply to the
	     prompt about the existing file.  It may also be due to the
	     use of the --reply=no option.  */
	  if (!S_ISDIR (src_type))
	    {
	      /* cp and mv treat -i and -f differently.  */
	      if (x->move_mode)
		{
		  if ((x->interactive == I_ALWAYS_NO
		       && UNWRITABLE (dst_path, dst_sb.st_mode))
		      || ((x->interactive == I_ASK_USER
			   || (x->interactive == I_UNSPECIFIED
			       && x->stdin_tty
			       && UNWRITABLE (dst_path, dst_sb.st_mode)))
			  && (overwrite_prompt (dst_path, &dst_sb), 1)
			  && ! yesno ()))
		    {
		      /* Pretend the rename succeeded, so the caller (mv)
			 doesn't end up removing the source file.  */
		      if (rename_succeeded)
			*rename_succeeded = 1;
		      return 0;
		    }
		}
	      else
		{
		  if (x->interactive == I_ALWAYS_NO
		      || (x->interactive == I_ASK_USER
			  && (overwrite_prompt (dst_path, &dst_sb), 1)
			  && ! yesno ()))
		    {
		      return 0;
		    }
		}
	    }

	  if (x->move_mode)
	    {
	      /* In move_mode, DEST may not be an existing directory.  */
	      if (S_ISDIR (dst_sb.st_mode))
		{
		  error (0, 0, _("cannot overwrite directory %s"),
			 quote (dst_path));
		  return 1;
		}

	      /* Don't allow user to move a directory onto a non-directory.  */
	      if (S_ISDIR (src_sb.st_mode) && !S_ISDIR (dst_sb.st_mode))
		{
		  error (0, 0,
		       _("cannot move directory onto non-directory: %s -> %s"),
			 quote_n (0, src_path), quote_n (0, dst_path));
		  return 1;
		}
	    }

	  if (x->backup_type != none && !S_ISDIR (dst_sb.st_mode))
	    {
	      char *tmp_backup = find_backup_file_name (dst_path,
							x->backup_type);
	      if (tmp_backup == NULL)
		xalloc_die ();

	      /* Detect (and fail) when creating the backup file would
		 destroy the source file.  Before, running the commands
		 cd /tmp; rm -f a a~; : > a; echo A > a~; cp --b=simple a~ a
		 would leave two zero-length files: a and a~.  */
	      /* FIXME: but simply change e.g., the final a~ to `./a~'
		 and the source will still be destroyed.  */
	      if (STREQ (tmp_backup, src_path))
		{
		  const char *fmt;
		  fmt = (x->move_mode
		 ? _("backing up %s would destroy source;  %s not moved")
		 : _("backing up %s would destroy source;  %s not copied"));
		  error (0, 0, fmt,
			 quote_n (0, dst_path),
			 quote_n (1, src_path));
		  free (tmp_backup);
		  return 1;
		}

	      dst_backup = (char *) alloca (strlen (tmp_backup) + 1);
	      strcpy (dst_backup, tmp_backup);
	      free (tmp_backup);
	      if (rename (dst_path, dst_backup))
		{
		  if (errno != ENOENT)
		    {
		      error (0, errno, _("cannot backup %s"), quote (dst_path));
		      return 1;
		    }
		  else
		    {
		      dst_backup = NULL;
		    }
		}
	      else
		{
		  backup_succeeded = 1;
		}
	      new_dst = 1;
	    }
	  else if (! S_ISDIR (dst_sb.st_mode)
		   && (x->unlink_dest_before_opening
		       || (x->xstat == lstat
			   && ! S_ISREG (src_sb.st_mode))))
	    {
	      if (unlink (dst_path) && errno != ENOENT)
		{
		  error (0, errno, _("cannot remove %s"), quote (dst_path));
		  return 1;
		}
	      new_dst = 1;
	    }
	}
    }

  /* If the source is a directory, we don't always create the destination
     directory.  So --verbose should not announce anything until we're
     sure we'll create a directory. */
  if (x->verbose && !S_ISDIR (src_type))
    {
      printf ("%s -> %s", quote_n (0, src_path), quote_n (1, dst_path));
      if (backup_succeeded)
	printf (_(" (backup: %s)"), quote (dst_backup));
      putchar ('\n');
    }

  /* Associate the destination path with the source device and inode
     so that if we encounter a matching dev/ino pair in the source tree
     we can arrange to create a hard link between the corresponding names
     in the destination tree.

     Sometimes, when preserving links, we have to record dev/ino even
     though st_nlink == 1:
     - when using -H and processing a command line argument;
	that command line argument could be a symlink pointing to another
	command line argument.  With `cp -H --preserve=link', we hard-link
	those two destination files.
     - likewise for -L except that it applies to all files, not just
	command line arguments.

     Also record directory dev/ino when using --recursive.  We'll use that
     info to detect this problem: cp -R dir dir.  FIXME-maybe: ideally,
     directory info would be recorded in a separate hash table, since
     such entries are useful only while a single command line hierarchy
     is being copied -- so that separate table could be cleared between
     command line args.  Using the same hash table to preserve hard
     links means that it may not be cleared.  */

  if ((x->preserve_links
       && (1 < src_sb.st_nlink
	   || (command_line_arg
	       && x->dereference == DEREF_COMMAND_LINE_ARGUMENTS)
	   || x->dereference == DEREF_ALWAYS))
      || (x->recursive && S_ISDIR (src_type)))
    {
      earlier_file = remember_copied (dst_path, src_sb.st_ino, src_sb.st_dev);
    }

  /* Did we copy this inode somewhere else (in this command line argument)
     and therefore this is a second hard link to the inode?  */

  if (earlier_file)
    {
      /* Avoid damaging the destination filesystem by refusing to preserve
	 hard-linked directories (which are found at least in Netapp snapshot
	 directories).  */
      if (S_ISDIR (src_type))
	{
	  /* If src_path and earlier_file refer to the same directory entry,
	     then warn about copying a directory into itself.  */
	  if (same_name (src_path, earlier_file))
	    {
	      error (0, 0, _("cannot copy a directory, %s, into itself, %s"),
		     quote_n (0, top_level_src_path),
		     quote_n (1, top_level_dst_path));
	      *copy_into_self = 1;
	    }
	  else
	    {
	      error (0, 0, _("will not create hard link %s to directory %s"),
		     quote_n (0, dst_path), quote_n (1, earlier_file));
	    }

	  goto un_backup;
	}

      {
	int link_failed;

	link_failed = link (earlier_file, dst_path);

	/* If the link failed because of an existing destination,
	   remove that file and then call link again.  */
	if (link_failed && errno == EEXIST)
	  {
	    if (unlink (dst_path))
	      {
		error (0, errno, _("cannot remove %s"), quote (dst_path));
		goto un_backup;
	      }
	    link_failed = link (earlier_file, dst_path);
	  }

	if (link_failed)
	  {
	    error (0, errno, _("cannot create hard link %s to %s"),
		   quote_n (0, dst_path), quote_n (1, earlier_file));
	    goto un_backup;
	  }

	return 0;
      }
    }

  if (x->move_mode)
    {
      if (rename (src_path, dst_path) == 0)
	{
	  if (x->verbose && S_ISDIR (src_type))
	    printf ("%s -> %s\n", quote_n (0, src_path), quote_n (1, dst_path));
	  if (rename_succeeded)
	    *rename_succeeded = 1;

	  if (command_line_arg)
	    {
	      /* Record destination dev/ino/filename, so that if we are asked
		 to overwrite that file again, we can detect it and fail.  */
	      /* It's fine to use the _source_ stat buffer (src_sb) to get the
	         _destination_ dev/ino, since the rename above can't have
		 changed those, and `mv' always uses lstat.
		 We could limit it further by operating
		 only on non-directories.  */
	      record_file (x->dest_info, dst_path, &src_sb);
	    }

	  return 0;
	}

      /* FIXME: someday, consider what to do when moving a directory into
	 itself but when source and destination are on different devices.  */

      /* This happens when attempting to rename a directory to a
	 subdirectory of itself.  */
      if (errno == EINVAL

	  /* When src_path is on an NFS file system, some types of
	     clients, e.g., SunOS4.1.4 and IRIX-5.3, set errno to EIO
	     instead.  Testing for this here risks misinterpreting a real
	     I/O error as an attempt to move a directory into itself, so
	     FIXME: consider not doing this.  */
	  || errno == EIO

	  /* And with SunOS-4.1.4 client and OpenBSD-2.3 server,
	     we get ENOTEMPTY.  */
	  || errno == ENOTEMPTY)
	{
	  /* FIXME: this is a little fragile in that it relies on rename(2)
	     failing with a specific errno value.  Expect problems on
	     non-POSIX systems.  */
	  error (0, 0, _("cannot move %s to a subdirectory of itself, %s"),
		 quote_n (0, top_level_src_path),
		 quote_n (1, top_level_dst_path));

	  /* Note that there is no need to call forget_created here,
	     (compare with the other calls in this file) since the
	     destination directory didn't exist before.  */

	  *copy_into_self = 1;
	  /* FIXME-cleanup: Don't return zero here; adjust mv.c accordingly.
	     The only caller that uses this code (mv.c) ends up setting its
	     exit status to nonzero when copy_into_self is nonzero.  */
	  return 0;
	}

      /* WARNING: there probably exist systems for which an inter-device
	 rename fails with a value of errno not handled here.
	 If/as those are reported, add them to the condition below.
	 If this happens to you, please do the following and send the output
	 to the bug-reporting address (e.g., in the output of cp --help):
	   touch k; perl -e 'rename "k","/tmp/k" or print "$!(",$!+0,")\n"'
	 where your current directory is on one partion and /tmp is the other.
	 Also, please try to find the E* errno macro name corresponding to
	 the diagnostic and parenthesized integer, and include that in your
	 e-mail.  One way to do that is to run a command like this
	   find /usr/include/. -type f \
	     | xargs grep 'define.*\<E[A-Z]*\>.*\<18\>' /dev/null
	 where you'd replace `18' with the integer in parentheses that
	 was output from the perl one-liner above.
	 If necessary, of course, change `/tmp' to some other directory.  */
      if (errno != EXDEV)
	{
	  /* There are many ways this can happen due to a race condition.
	     When something happens between the initial xstat and the
	     subsequent rename, we can get many different types of errors.
	     For example, if the destination is initially a non-directory
	     or non-existent, but it is created as a directory, the rename
	     fails.  If two `mv' commands try to rename the same file at
	     about the same time, one will succeed and the other will fail.
	     If the permissions on the directory containing the source or
	     destination file are made too restrictive, the rename will
	     fail.  Etc.  */
	  error (0, errno,
		 _("cannot move %s to %s"),
		 quote_n (0, src_path), quote_n (1, dst_path));
	  forget_created (src_sb.st_ino, src_sb.st_dev);
	  return 1;
	}

      /* The rename attempt has failed.  Remove any existing destination
	 file so that a cross-device `mv' acts as if it were really using
	 the rename syscall.  */
      if (unlink (dst_path) && errno != ENOENT)
	{
	  error (0, errno,
	     _("inter-device move failed: %s to %s; unable to remove target"),
		 quote_n (0, src_path), quote_n (1, dst_path));
	  forget_created (src_sb.st_ino, src_sb.st_dev);
	  return 1;
	}

      new_dst = 1;
    }

  delayed_fail = 0;

  /* In certain modes (cp's --symbolic-link), and for certain file types
     (symlinks and hard links) it doesn't make sense to preserve metadata,
     or it's possible to preserve only some of it.
     In such cases, set this variable to zero.  */
  preserve_metadata = 1;

  if (S_ISDIR (src_type))
    {
      struct dir_list *dir;

      /* If this directory has been copied before during the
         recursion, there is a symbolic link to an ancestor
         directory of the symbolic link.  It is impossible to
         continue to copy this, unless we've got an infinite disk.  */

      if (is_ancestor (&src_sb, ancestors))
	{
	  error (0, 0, _("cannot copy cyclic symbolic link %s"),
		 quote (src_path));
	  goto un_backup;
	}

      /* Insert the current directory in the list of parents.  */

      dir = (struct dir_list *) alloca (sizeof (struct dir_list));
      dir->parent = ancestors;
      dir->ino = src_sb.st_ino;
      dir->dev = src_sb.st_dev;

      if (new_dst || !S_ISDIR (dst_sb.st_mode))
	{
	  /* Create the new directory writable and searchable, so
             we can create new entries in it.  */

	  if (mkdir (dst_path, (src_mode & x->umask_kill) | S_IRWXU))
	    {
	      error (0, errno, _("cannot create directory %s"),
		     quote (dst_path));
	      goto un_backup;
	    }

	  /* Insert the created directory's inode and device
             numbers into the search structure, so that we can
             avoid copying it again.  */

	  if (remember_created (dst_path))
	    goto un_backup;

	  if (x->verbose)
	    printf ("%s -> %s\n", quote_n (0, src_path), quote_n (1, dst_path));
	}

      /* Are we crossing a file system boundary?  */
      if (x->one_file_system && device != 0 && device != src_sb.st_dev)
	return 0;

      /* Copy the contents of the directory.  */

      if (copy_dir (src_path, dst_path, new_dst, &src_sb, dir, x,
		    copy_into_self))
	{
	  /* Don't just return here -- otherwise, the failure to read a
	     single file in a source directory would cause the containing
	     destination directory not to have owner/perms set properly.  */
	  delayed_fail = 1;
	}
    }
#ifdef S_ISLNK
  else if (x->symbolic_link)
    {
      preserve_metadata = 0;

      if (*src_path != '/')
	{
	  /* Check that DST_PATH denotes a file in the current directory.  */
	  struct stat dot_sb;
	  struct stat dst_parent_sb;
	  char *dst_parent;
	  int in_current_dir;

	  dst_parent = dir_name (dst_path);

	  in_current_dir = (STREQ (".", dst_parent)
			    /* If either stat call fails, it's ok not to report
			       the failure and say dst_path is in the current
			       directory.  Other things will fail later.  */
			    || stat (".", &dot_sb)
			    || stat (dst_parent, &dst_parent_sb)
			    || SAME_INODE (dot_sb, dst_parent_sb));
	  free (dst_parent);

	  if (! in_current_dir)
	    {
	      error (0, 0,
	   _("%s: can make relative symbolic links only in current directory"),
		     quote (dst_path));
	      goto un_backup;
	    }
	}
      if (symlink (src_path, dst_path))
	{
	  error (0, errno, _("cannot create symbolic link %s to %s"),
		 quote_n (0, dst_path), quote_n (1, src_path));
	  goto un_backup;
	}
    }
#endif
  else if (x->hard_link)
    {
      preserve_metadata = 0;
      if (link (src_path, dst_path))
	{
	  error (0, errno, _("cannot create link %s"), quote (dst_path));
	  goto un_backup;
	}
    }
  else if (S_ISREG (src_type)
	   || (x->copy_as_regular && !S_ISDIR (src_type)
#ifdef S_ISLNK
	       && !S_ISLNK (src_type)
#endif
	       ))
    {
      copied_as_regular = 1;
      /* POSIX says the permission bits of the source file must be
	 used as the 3rd argument in the open call, but that's not consistent
	 with historical practice.  */
      if (copy_reg (src_path, dst_path, x,
		    get_dest_mode (x, src_mode), &new_dst, &src_sb))
	goto un_backup;
    }
  else
#ifdef S_ISFIFO
  if (S_ISFIFO (src_type))
    {
      if (mkfifo (dst_path, get_dest_mode (x, src_mode)))
	{
	  error (0, errno, _("cannot create fifo %s"), quote (dst_path));
	  goto un_backup;
	}
    }
  else
#endif
    if (S_ISBLK (src_type) || S_ISCHR (src_type)
#ifdef S_ISSOCK
	|| S_ISSOCK (src_type)
#endif
	)
    {
      if (mknod (dst_path, get_dest_mode (x, src_mode), src_sb.st_rdev))
	{
	  error (0, errno, _("cannot create special file %s"),
		 quote (dst_path));
	  goto un_backup;
	}
    }
  else
#ifdef S_ISLNK
  if (S_ISLNK (src_type))
    {
      char *src_link_val = xreadlink (src_path);
      if (src_link_val == NULL)
	{
	  error (0, errno, _("cannot read symbolic link %s"), quote (src_path));
	  goto un_backup;
	}

      if (!symlink (src_link_val, dst_path))
	free (src_link_val);
      else
	{
	  int saved_errno = errno;
	  int same_link = 0;
	  if (x->update && !new_dst && S_ISLNK (dst_sb.st_mode))
	    {
	      /* See if the destination is already the desired symlink.  */
	      size_t src_link_len = strlen (src_link_val);
	      char *dest_link_val = (char *) alloca (src_link_len + 1);
	      int dest_link_len = readlink (dst_path, dest_link_val,
					    src_link_len + 1);
	      if ((size_t) dest_link_len == src_link_len
		  && strncmp (dest_link_val, src_link_val, src_link_len) == 0)
		same_link = 1;
	    }
	  free (src_link_val);

	  if (! same_link)
	    {
	      error (0, saved_errno, _("cannot create symbolic link %s"),
		     quote (dst_path));
	      goto un_backup;
	    }
	}

      /* There's no need to preserve timestamps or permissions.  */
      preserve_metadata = 0;

      if (x->preserve_ownership)
	{
	  /* Preserve the owner and group of the just-`copied'
	     symbolic link, if possible.  */
# if HAVE_LCHOWN
	  if (DO_CHOWN (lchown, dst_path, src_sb.st_uid, src_sb.st_gid))
	    {
	      error (0, errno, _("failed to preserve ownership for %s"),
		     dst_path);
	      goto un_backup;
	    }
# else
	  /* Can't preserve ownership of symlinks.
	     FIXME: maybe give a warning or even error for symlinks
	     in directories with the sticky bit set -- there, not
	     preserving owner/group is a potential security problem.  */
# endif
	}
    }
  else
#endif
    {
      error (0, 0, _("%s has unknown file type"), quote (src_path));
      goto un_backup;
    }

  if (command_line_arg)
    record_file (x->dest_info, dst_path, NULL);

  if ( ! preserve_metadata)
    return 0;

  /* POSIX says that `cp -p' must restore the following:
     - permission bits
     - setuid, setgid bits
     - owner and group
     If it fails to restore any of those, we may give a warning but
     the destination must not be removed.
     FIXME: implement the above. */

  /* Adjust the times (and if possible, ownership) for the copy.
     chown turns off set[ug]id bits for non-root,
     so do the chmod last.  */

  if (x->preserve_timestamps)
    {
      struct utimbuf utb;

      /* There's currently no interface to set file timestamps with
	 better than 1-second resolution, so discard any fractional
	 part of the source timestamp.  */

      utb.actime = src_sb.st_atime;
      utb.modtime = src_sb.st_mtime;

      if (utime (dst_path, &utb))
	{
	  error (0, errno, _("preserving times for %s"), quote (dst_path));
	  if (x->require_preserve)
	    return 1;
	}
    }

  /* Avoid calling chown if we know it's not necessary.  */
  if (x->preserve_ownership
      && (new_dst || !SAME_OWNER_AND_GROUP (src_sb, dst_sb)))
    {
      ran_chown = 1;
      if (DO_CHOWN (chown, dst_path, src_sb.st_uid, src_sb.st_gid))
	{
	  error (0, errno, _("failed to preserve ownership for %s"),
		 quote (dst_path));
	  if (x->require_preserve)
	    return 1;
	}
    }

#if HAVE_STRUCT_STAT_ST_AUTHOR
  /* Preserve the st_author field.  */
  {
    file_t file = file_name_lookup (dst_path, 0, 0);
    if (file_chauthor (file, src_sb.st_author))
      error (0, errno, _("failed to preserve authorship for %s"),
	     quote (dst_path));
    mach_port_deallocate (mach_task_self (), file);
  }
#endif

  /* Permissions of newly-created regular files were set upon `open' in
     copy_reg.  But don't return early if there were any special bits and
     we had to run chown, because the chown must have reset those bits.  */
  if ((new_dst && copied_as_regular)
      && !(ran_chown && (src_mode & ~S_IRWXUGO)))
    return delayed_fail;

  if ((x->preserve_mode || new_dst)
      && (x->copy_as_regular || S_ISREG (src_type) || S_ISDIR (src_type)))
    {
      if (chmod (dst_path, get_dest_mode (x, src_mode)))
	{
	  error (0, errno, _("setting permissions for %s"), quote (dst_path));
	  if (x->set_mode || x->require_preserve)
	    return 1;
	}
    }

  return delayed_fail;

un_backup:

  /* We have failed to create the destination file.
     If we've just added a dev/ino entry via the remember_copied
     call above (i.e., unless we've just failed to create a hard link),
     remove the entry associating the source dev/ino with the
     destination file name, so we don't try to `preserve' a link
     to a file we didn't create.  */
  if (earlier_file == NULL)
    forget_created (src_sb.st_ino, src_sb.st_dev);

  if (dst_backup)
    {
      if (rename (dst_backup, dst_path))
	error (0, errno, _("cannot un-backup %s"), quote (dst_path));
      else
	{
	  if (x->verbose)
	    printf (_("%s -> %s (unbackup)\n"),
		    quote_n (0, dst_backup), quote_n (1, dst_path));
	}
    }
  return 1;
}
Beispiel #5
0
int rpmfiConfigConflictIndex(rpmfi fi, int ix)
{
    char * fn = NULL;
    rpmfileAttrs flags = rpmfiFFlagsIndex(fi, ix);
    char buffer[1024];
    rpmFileTypes newWhat, diskWhat;
    struct stat sb;
    int rc = 0;

    /* Non-configs are not config conflicts. */
    if (!(flags & RPMFILE_CONFIG))
	return 0;

    /* Only links and regular files can be %config, this is kinda moot */
    /* XXX: Why are we returning 1 here? */
    newWhat = rpmfiWhatis(rpmfiFModeIndex(fi, ix));
    if (newWhat != LINK && newWhat != REG)
	return 1;

    /* If it's not on disk, there's nothing to be saved */
    fn = rpmfiFNIndex(fi, ix);
    if (lstat(fn, &sb))
	goto exit;

    /*
     * Preserve legacy behavior: an existing %ghost %config is considered
     * "modified" but unlike regular %config, its never removed and
     * never backed up. Whether this actually makes sense is a whole
     * another question, but this is very long-standing behavior that
     * people might be depending on. The resulting FA_ALTNAME etc action
     * is special-cased in FSM to avoid actually creating backups on ghosts.
     */
    if (flags & RPMFILE_GHOST) {
	rc = 1;
	goto exit;
    }

    /* Files of different types obviously are not identical */
    diskWhat = rpmfiWhatis((rpm_mode_t)sb.st_mode);
    if (diskWhat != newWhat) {
	rc = 1;
	goto exit;
    }

    /* Files of different sizes obviously are not identical */
    if (rpmfiFSizeIndex(fi, ix) != sb.st_size) {
	rc = 1;
	goto exit;
    }
    
    memset(buffer, 0, sizeof(buffer));
    if (newWhat == REG) {
	int algo;
	size_t diglen;
	const unsigned char *ndigest = rpmfiFDigestIndex(fi,ix, &algo, &diglen);
	if (rpmDoDigest(algo, fn, 0, (unsigned char *)buffer, NULL))
	    goto exit;	/* assume file has been removed */
	if (ndigest && memcmp(ndigest, buffer, diglen) == 0)
	    goto exit;	/* unmodified config file */
    } else /* newWhat == LINK */ {
	const char * nFLink;
	ssize_t link_len = readlink(fn, buffer, sizeof(buffer) - 1);
	if (link_len == -1)
	    goto exit;	/* assume file has been removed */
	buffer[link_len] = '\0';
	nFLink = rpmfiFLinkIndex(fi, ix);
	if (nFLink && rstreq(nFLink, buffer))
	    goto exit;	/* unmodified config file */
    }

    rc = 1;

exit:
    free(fn);
    return rc;
}
char *
chroot_canon (const char *chroot, const char *name)
{
  char *rpath;
  char *dest;
  char *extra_buf = NULL;
  char *rpath_root;
  const char *start;
  const char *end;
  const char *rpath_limit;
  int num_links = 0;
  size_t chroot_len = strlen (chroot);

  if (chroot_len < 1)
    {
      __set_errno (EINVAL);
      return NULL;
    }

  rpath = malloc (chroot_len + PATH_MAX);
  if (rpath == NULL)
    return NULL;

  rpath_limit = rpath + chroot_len + PATH_MAX;

  rpath_root = (char *) mempcpy (rpath, chroot, chroot_len) - 1;
  if (*rpath_root != '/')
    *++rpath_root = '/';
  dest = rpath_root + 1;

  for (start = end = name; *start; start = end)
    {
      struct stat64 st;
      int n;

      /* Skip sequence of multiple path-separators.  */
      while (*start == '/')
	++start;

      /* Find end of path component.  */
      for (end = start; *end && *end != '/'; ++end)
	/* Nothing.  */;

      if (end - start == 0)
	break;
      else if (end - start == 1 && start[0] == '.')
	/* nothing */;
      else if (end - start == 2 && start[0] == '.' && start[1] == '.')
	{
	  /* Back up to previous component, ignore if at root already.  */
	  if (dest > rpath_root + 1)
	    while ((--dest)[-1] != '/');
	}
      else
	{
	  size_t new_size;

	  if (dest[-1] != '/')
	    *dest++ = '/';

	  if (dest + (end - start) >= rpath_limit)
	    {
	      ptrdiff_t dest_offset = dest - rpath;
	      char *new_rpath;

	      new_size = rpath_limit - rpath;
	      if (end - start + 1 > PATH_MAX)
		new_size += end - start + 1;
	      else
		new_size += PATH_MAX;
	      new_rpath = (char *) realloc (rpath, new_size);
	      if (new_rpath == NULL)
		goto error;
	      rpath = new_rpath;
	      rpath_limit = rpath + new_size;

	      dest = rpath + dest_offset;
	    }

	  dest = mempcpy (dest, start, end - start);
	  *dest = '\0';

	  if (lstat64 (rpath, &st) < 0)
	    {
	      if (*end == '\0')
		goto done;
	      goto error;
	    }

	  if (S_ISLNK (st.st_mode))
	    {
	      char *buf = alloca (PATH_MAX);
	      size_t len;

	      if (++num_links > MAXSYMLINKS)
		{
		  __set_errno (ELOOP);
		  goto error;
		}

	      n = readlink (rpath, buf, PATH_MAX);
	      if (n < 0)
		{
		  if (*end == '\0')
		    goto done;
		  goto error;
		}
	      buf[n] = '\0';

	      if (!extra_buf)
		extra_buf = alloca (PATH_MAX);

	      len = strlen (end);
	      if ((long int) (n + len) >= PATH_MAX)
		{
		  __set_errno (ENAMETOOLONG);
		  goto error;
		}

	      /* Careful here, end may be a pointer into extra_buf... */
	      memmove (&extra_buf[n], end, len + 1);
	      name = end = memcpy (extra_buf, buf, n);

	      if (buf[0] == '/')
		dest = rpath_root + 1;	/* It's an absolute symlink */
	      else
		/* Back up to previous component, ignore if at root already: */
		if (dest > rpath_root + 1)
		  while ((--dest)[-1] != '/');
	    }
	}
    }
 done:
  if (dest > rpath_root + 1 && dest[-1] == '/')
    --dest;
  *dest = '\0';

  return rpath;

 error:
  free (rpath);
  return NULL;
}
Beispiel #7
0
LLDir_Linux::LLDir_Linux()
{
	mDirDelimiter = "/";
	mCurrentDirIndex = -1;
	mCurrentDirCount = -1;
	mDirp = NULL;

	char tmp_str[LL_MAX_PATH];	/* Flawfinder: ignore */ 
	if (getcwd(tmp_str, LL_MAX_PATH) == NULL)
	{
		strcpy(tmp_str, "/tmp");
		llwarns << "Could not get current directory; changing to "
				<< tmp_str << llendl;
		if (chdir(tmp_str) == -1)
		{
			llerrs << "Could not change directory to " << tmp_str << llendl;
		}
	}

	mExecutableFilename = "";
	mExecutablePathAndName = "";
	mExecutableDir = tmp_str;
	mWorkingDir = tmp_str;
	mAppRODataDir = tmp_str;
	mOSUserDir = getCurrentUserHome(tmp_str);
	mOSUserAppDir = "";
	mLindenUserDir = tmp_str;

	char path [32];	/* Flawfinder: ignore */ 

	// *NOTE: /proc/%d/exe doesn't work on FreeBSD. But that's ok,
	// because this is the linux implementation.

	snprintf (path, sizeof(path), "/proc/%d/exe", (int) getpid ()); 
	int rc = readlink (path, tmp_str, sizeof (tmp_str)-1);	/* Flawfinder: ignore */ 
	if ( (rc != -1) && (rc <= ((int) sizeof (tmp_str)-1)) )
	{
		tmp_str[rc] = '\0'; //readlink() doesn't 0-terminate the buffer
		mExecutablePathAndName = tmp_str;
		char *path_end;
		if ((path_end = strrchr(tmp_str,'/')))
		{
			*path_end = '\0';
			mExecutableDir = tmp_str;
			mWorkingDir = tmp_str;
			mExecutableFilename = path_end+1;
		}
		else
		{
			mExecutableFilename = tmp_str;
		}
	}

	mLLPluginDir = mExecutableDir + mDirDelimiter + "llplugin";

#ifdef APP_RO_DATA_DIR
        const char* appRODataDir = APP_RO_DATA_DIR;
        if(appRODataDir[0] == '/')
          {
          // We have a full path to the data directory.
          mAppRODataDir = appRODataDir;
          }
        else if(appRODataDir[0] != '\0')
          {
          // We have a relative path to the data directory.  Search
          // for it in each potential install prefix containing the
          // executable.
          for(std::string prefix = getDirName(mExecutableDir);
              !prefix.empty(); prefix = getDirName(prefix))
            {
            std::string dir = prefix + "/" + appRODataDir;
            if(fileExists(dir + "/app_settings"))
              {
              mAppRODataDir = dir;
              break;
              }
            }
          }
#endif

	// *TODO: don't use /tmp, use $HOME/.secondlife/tmp or something.
	mTempDir = "/tmp";
}
//static
QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data)
{
#if defined(__GLIBC__) && !defined(PATH_MAX)
#define PATH_CHUNK_SIZE 256
    char *s = 0;
    int len = -1;
    int size = PATH_CHUNK_SIZE;

    while (1) {
        s = (char *) ::realloc(s, size);
        Q_CHECK_PTR(s);
        len = ::readlink(link.nativeFilePath().constData(), s, size);
        if (len < 0) {
            ::free(s);
            break;
        }
        if (len < size) {
            break;
        }
        size *= 2;
    }
#else
    char s[PATH_MAX+1];
    int len = readlink(link.nativeFilePath().constData(), s, PATH_MAX);
#endif
    if (len > 0) {
        QString ret;
        if (!data.hasFlags(QFileSystemMetaData::DirectoryType))
            fillMetaData(link, data, QFileSystemMetaData::DirectoryType);
        if (data.isDirectory() && s[0] != '/') {
            QDir parent(link.filePath());
            parent.cdUp();
            ret = parent.path();
            if (!ret.isEmpty() && !ret.endsWith(QLatin1Char('/')))
                ret += QLatin1Char('/');
        }
        s[len] = '\0';
        ret += QFile::decodeName(QByteArray(s));
#if defined(__GLIBC__) && !defined(PATH_MAX)
        ::free(s);
#endif

        if (!ret.startsWith(QLatin1Char('/'))) {
            if (link.filePath().startsWith(QLatin1Char('/'))) {
                ret.prepend(link.filePath().left(link.filePath().lastIndexOf(QLatin1Char('/')))
                            + QLatin1Char('/'));
            } else {
                ret.prepend(QDir::currentPath() + QLatin1Char('/'));
            }
        }
        ret = QDir::cleanPath(ret);
        if (ret.size() > 1 && ret.endsWith(QLatin1Char('/')))
            ret.chop(1);
        return QFileSystemEntry(ret);
    }
#if defined(Q_OS_DARWIN)
    {
        QCFString path = CFStringCreateWithFileSystemRepresentation(0,
            QFile::encodeName(QDir::cleanPath(link.filePath())).data());
        if (!path)
            return QFileSystemEntry();

        QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, path, kCFURLPOSIXPathStyle,
            data.hasFlags(QFileSystemMetaData::DirectoryType));
        if (!url)
            return QFileSystemEntry();

        QCFType<CFDataRef> bookmarkData = CFURLCreateBookmarkDataFromFile(0, url, NULL);
        if (!bookmarkData)
            return QFileSystemEntry();

        QCFType<CFURLRef> resolvedUrl = CFURLCreateByResolvingBookmarkData(0,
            bookmarkData,
            (CFURLBookmarkResolutionOptions)(kCFBookmarkResolutionWithoutUIMask
                | kCFBookmarkResolutionWithoutMountingMask), NULL, NULL, NULL, NULL);
        if (!resolvedUrl)
            return QFileSystemEntry();

        QCFString cfstr(CFURLCopyFileSystemPath(resolvedUrl, kCFURLPOSIXPathStyle));
        if (!cfstr)
            return QFileSystemEntry();

        return QFileSystemEntry(QCFString::toQString(cfstr));
    }
#endif
    return QFileSystemEntry();
}
Beispiel #9
0
/** @internal
 * Find the canonical filename of the executable. Returns the filename
 * (which must be freed) or NULL on error. If the parameter 'error' is
 * not NULL, the error code will be stored there, if an error occured.
 */
static char *
_br_find_exe (BrInitError *error)
{
#ifndef ENABLE_BINRELOC
	if (error)
		*error = BR_INIT_ERROR_DISABLED;
	return NULL;
#elif defined(sun) || defined(__sun)
	char *path;
	path = getexecname();
	return strdup(path);
#elif defined(__APPLE__) && defined(__MACH__)
    char path[MAXPATHLEN+1];
    uint32_t path_len = MAXPATHLEN;
    // SPI first appeared in Mac OS X 10.2
    _NSGetExecutablePath(path, &path_len);
    return strdup(path);
#else
	char *path, *path2, *line, *result;
	size_t buf_size;
	ssize_t size;
	struct stat stat_buf;
	FILE *f;

	/* Read from /proc/self/exe (symlink) */
	if (sizeof (path) > SSIZE_MAX)
		buf_size = SSIZE_MAX - 1;
	else
		buf_size = PATH_MAX - 1;
	path = (char *) malloc (buf_size);
	if (path == NULL) {
		/* Cannot allocate memory. */
		if (error)
			*error = BR_INIT_ERROR_NOMEM;
		return NULL;
	}
	path2 = (char *) malloc (buf_size);
	if (path2 == NULL) {
		/* Cannot allocate memory. */
		if (error)
			*error = BR_INIT_ERROR_NOMEM;
		free (path);
		return NULL;
	}

#ifdef __FreeBSD__
	strncpy (path2, "/proc/self/file", buf_size - 1);
#else
	strncpy (path2, "/proc/self/exe", buf_size - 1);
#endif

	while (1) {
		int i;

		size = readlink (path2, path, buf_size - 1);
		if (size == -1) {
			/* Error. */
			free (path2);
			break;
		}

		/* readlink() success. */
		path[size] = '\0';

		/* Check whether the symlink's target is also a symlink.
		 * We want to get the final target. */
		i = stat (path, &stat_buf);
		if (i == -1) {
			/* Error. */
			free (path2);
			break;
		}

		/* stat() success. */
		if (!S_ISLNK (stat_buf.st_mode)) {
			/* path is not a symlink. Done. */
			free (path2);
			return path;
		}

		/* path is a symlink. Continue loop and resolve this. */
		strncpy (path, path2, buf_size - 1);
	}

#if defined(__FreeBSD__)
{
    char *name, *start, *end;
	char *buffer = NULL, *temp;
	struct stat finfo;

	name = (char*) getprogname();
    start = end = getenv("PATH");

    while (*end) {
	 end = strchr (start, ':');
	 if (!end) end = strchr (start, '\0');

	 /* Resize `buffer' for path component, '/', name and a '\0' */
	 temp = realloc (buffer, end - start + 1 + strlen (name) + 1);
	 if (temp) {
	    buffer = temp;

	    strncpy (buffer, start, end - start);
	    *(buffer + (end - start)) = '/';
	    strcpy (buffer + (end - start) + 1, name);

	    if ((stat(buffer, &finfo)==0) && (!S_ISDIR (finfo.st_mode))) {
	       path = strdup(buffer);
	       free (buffer);
	       return path;
	    }
	 } /* else... ignore the failure; `buffer' is still valid anyway. */

	 start = end + 1;
      }
      /* Path search failed */
      free (buffer);

	if (error)
		*error = BR_INIT_ERROR_DISABLED;
	return NULL;
}
#endif

	/* readlink() or stat() failed; this can happen when the program is
	 * running in Valgrind 2.2. Read from /proc/self/maps as fallback. */

	buf_size = PATH_MAX + 128;
	line = (char *) realloc (path, buf_size);
	if (line == NULL) {
		/* Cannot allocate memory. */
		free (path);
		if (error)
			*error = BR_INIT_ERROR_NOMEM;
		return NULL;
	}

	f = fopen ("/proc/self/maps", "r");
	if (f == NULL) {
		free (line);
		if (error)
			*error = BR_INIT_ERROR_OPEN_MAPS;
		return NULL;
	}

	/* The first entry should be the executable name. */
	result = fgets (line, (int) buf_size, f);
	if (result == NULL) {
		fclose (f);
		free (line);
		if (error)
			*error = BR_INIT_ERROR_READ_MAPS;
		return NULL;
	}

	/* Get rid of newline character. */
	buf_size = strlen (line);
	if (buf_size <= 0) {
		/* Huh? An empty string? */
		fclose (f);
		free (line);
		if (error)
			*error = BR_INIT_ERROR_INVALID_MAPS;
		return NULL;
	}
	if (line[buf_size - 1] == 10)
		line[buf_size - 1] = 0;

	/* Extract the filename; it is always an absolute path. */
	path = strchr (line, '/');

	/* Sanity check. */
	if (strstr (line, " r-xp ") == NULL || path == NULL) {
		fclose (f);
		free (line);
		if (error)
			*error = BR_INIT_ERROR_INVALID_MAPS;
		return NULL;
	}

	path = strdup (path);
	free (line);
	fclose (f);
	return path;
#endif /* ENABLE_BINRELOC */
}
Beispiel #10
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;
}
Beispiel #11
0
/*
 * Connects to i3 to find out the currently running version. Useful since it
 * might be different from the version compiled into this binary (maybe the
 * user didn’t correctly install i3 or forgot te restart it).
 *
 * The output looks like this:
 * Running i3 version: 4.2-202-gb8e782c (2012-08-12, branch "next") (pid 14804)
 *
 * The i3 binary you just called: /home/michael/i3/i3
 * The i3 binary you are running: /home/michael/i3/i3
 *
 */
void display_running_version(void) {
    char *socket_path = root_atom_contents("I3_SOCKET_PATH", conn, conn_screen);
    if (socket_path == NULL)
        exit(EXIT_SUCCESS);

    char *pid_from_atom = root_atom_contents("I3_PID", conn, conn_screen);
    if (pid_from_atom == NULL) {
        /* If I3_PID is not set, the running version is older than 4.2-200. */
        printf("\nRunning version: < 4.2-200\n");
        exit(EXIT_SUCCESS);
    }

    /* Inform the user of what we are doing. While a single IPC request is
     * really fast normally, in case i3 hangs, this will not terminate. */
    printf("(Getting version from running i3, press ctrl-c to abort…)");
    fflush(stdout);

    /* TODO: refactor this with the code for sending commands */
    int sockfd = socket(AF_LOCAL, SOCK_STREAM, 0);
    if (sockfd == -1)
        err(EXIT_FAILURE, "Could not create socket");

    struct sockaddr_un addr;
    memset(&addr, 0, sizeof(struct sockaddr_un));
    addr.sun_family = AF_LOCAL;
    strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
    if (connect(sockfd, (const struct sockaddr *)&addr, sizeof(struct sockaddr_un)) < 0)
        err(EXIT_FAILURE, "Could not connect to i3");

    if (ipc_send_message(sockfd, 0, I3_IPC_MESSAGE_TYPE_GET_VERSION,
                         (uint8_t *)"") == -1)
        err(EXIT_FAILURE, "IPC: write()");

    uint32_t reply_length;
    uint32_t reply_type;
    uint8_t *reply;
    int ret;
    if ((ret = ipc_recv_message(sockfd, &reply_type, &reply_length, &reply)) != 0) {
        if (ret == -1)
            err(EXIT_FAILURE, "IPC: read()");
        exit(EXIT_FAILURE);
    }

    if (reply_type != I3_IPC_MESSAGE_TYPE_GET_VERSION)
        errx(EXIT_FAILURE, "Got reply type %d, but expected %d (GET_VERSION)", reply_type, I3_IPC_MESSAGE_TYPE_GET_VERSION);

    yajl_handle handle = yajl_alloc(&version_callbacks, NULL, NULL);

    yajl_status state = yajl_parse(handle, (const unsigned char *)reply, (int)reply_length);
    if (state != yajl_status_ok)
        errx(EXIT_FAILURE, "Could not parse my own reply. That's weird. reply is %.*s", (int)reply_length, reply);

    printf("\rRunning i3 version: %s (pid %s)\n", human_readable_version, pid_from_atom);

    if (loaded_config_file_name) {
        struct stat sb;
        time_t now;
        char mtime[64];
        printf("Loaded i3 config: %s", loaded_config_file_name);
        if (stat(loaded_config_file_name, &sb) == -1) {
            printf("\n");
            ELOG("Cannot stat config file \"%s\"\n", loaded_config_file_name);
        } else {
            strftime(mtime, sizeof(mtime), "%c", localtime(&(sb.st_mtime)));
            time(&now);
            printf(" (Last modified: %s, %.f seconds ago)\n", mtime, difftime(now, sb.st_mtime));
        }
    }

#ifdef __linux__
    size_t destpath_size = 1024;
    ssize_t linksize;
    char *exepath;
    char *destpath = smalloc(destpath_size);

    sasprintf(&exepath, "/proc/%d/exe", getpid());

    while ((linksize = readlink(exepath, destpath, destpath_size)) == (ssize_t)destpath_size) {
        destpath_size = destpath_size * 2;
        destpath = srealloc(destpath, destpath_size);
    }
    if (linksize == -1)
        err(EXIT_FAILURE, "readlink(%s)", exepath);

    /* readlink() does not NULL-terminate strings, so we have to. */
    destpath[linksize] = '\0';

    printf("\n");
    printf("The i3 binary you just called: %s\n", destpath);

    free(exepath);
    sasprintf(&exepath, "/proc/%s/exe", pid_from_atom);

    while ((linksize = readlink(exepath, destpath, destpath_size)) == (ssize_t)destpath_size) {
        destpath_size = destpath_size * 2;
        destpath = srealloc(destpath, destpath_size);
    }
    if (linksize == -1)
        err(EXIT_FAILURE, "readlink(%s)", exepath);

    /* readlink() does not NULL-terminate strings, so we have to. */
    destpath[linksize] = '\0';

    /* Check if "(deleted)" is the readlink result. If so, the running version
     * does not match the file on disk. */
    if (strstr(destpath, "(deleted)") != NULL)
        printf("RUNNING BINARY DIFFERENT FROM BINARY ON DISK!\n");

    /* Since readlink() might put a "(deleted)" somewhere in the buffer and
     * stripping that out seems hackish and ugly, we read the process’s argv[0]
     * instead. */
    free(exepath);
    sasprintf(&exepath, "/proc/%s/cmdline", pid_from_atom);

    int fd;
    if ((fd = open(exepath, O_RDONLY)) == -1)
        err(EXIT_FAILURE, "open(%s)", exepath);
    if (read(fd, destpath, sizeof(destpath)) == -1)
        err(EXIT_FAILURE, "read(%s)", exepath);
    close(fd);

    printf("The i3 binary you are running: %s\n", destpath);

    free(exepath);
    free(destpath);
#endif

    yajl_free(handle);
}
Beispiel #12
0
int
next_file(ARCHD *arcn)
{
	int cnt;
	time_t atime;
	time_t mtime;

	/*
	 * ftree_sel() might have set the ftree_skip flag if the user has the
	 * -n option and a file was selected from this file arg tree. (-n says
	 * only one member is matched for each pattern) ftree_skip being 1
	 * forces us to go to the next arg now.
	 */
	if (ftree_skip) {
		/*
		 * clear and go to next arg
		 */
		ftree_skip = 0;
		if (ftree_arg() < 0)
			return(-1);
	}

	/*
	 * loop until we get a valid file to process
	 */
	for(;;) {
		if ((ftent = fts_read(ftsp)) == NULL) {
			/*
			 * out of files in this tree, go to next arg, if none
			 * we are done
			 */
			if (ftree_arg() < 0)
				return(-1);
			continue;
		}

		/*
		 * handle each type of fts_read() flag
		 */
		switch(ftent->fts_info) {
		case FTS_D:
		case FTS_DEFAULT:
		case FTS_F:
		case FTS_SL:
		case FTS_SLNONE:
			/*
			 * these are all ok
			 */
			break;
		case FTS_DP:
			/*
			 * already saw this directory. If the user wants file
			 * access times reset, we use this to restore the
			 * access time for this directory since this is the
			 * last time we will see it in this file subtree
			 * remember to force the time (this is -t on a read
			 * directory, not a created directory).
			 */
#			ifdef NET2_FTS
			if (!tflag || (get_atdir(ftent->fts_statb.st_dev,
			    ftent->fts_statb.st_ino, &mtime, &atime) < 0))
#			else
			if (!tflag || (get_atdir(ftent->fts_statp->st_dev,
			    ftent->fts_statp->st_ino, &mtime, &atime) < 0))
#			endif
				continue;
			set_ftime(ftent->fts_path, mtime, atime, 1);
			continue;
		case FTS_DC:
			/*
			 * fts claims a file system cycle
			 */
			paxwarn(1,"File system cycle found at %s",ftent->fts_path);
			continue;
		case FTS_DNR:
#			ifdef NET2_FTS
			syswarn(1, errno,
#			else
			syswarn(1, ftent->fts_errno,
#			endif
			    "Unable to read directory %s", ftent->fts_path);
			continue;
		case FTS_ERR:
#			ifdef NET2_FTS
			syswarn(1, errno,
#			else
			syswarn(1, ftent->fts_errno,
#			endif
			    "File system traversal error");
			continue;
		case FTS_NS:
		case FTS_NSOK:
#			ifdef NET2_FTS
			syswarn(1, errno,
#			else
			syswarn(1, ftent->fts_errno,
#			endif
			    "Unable to access %s", ftent->fts_path);
			continue;
		}

		/*
		 * ok got a file tree node to process. copy info into arcn
		 * structure (initialize as required)
		 */
		arcn->skip = 0;
		arcn->pad = 0;
		arcn->ln_nlen = 0;
		arcn->ln_name[0] = '\0';
#		ifdef NET2_FTS
		arcn->sb = ftent->fts_statb;
#		else
		arcn->sb = *(ftent->fts_statp);
#		endif

		/*
		 * file type based set up and copy into the arcn struct
		 * SIDE NOTE:
		 * we try to reset the access time on all files and directories
		 * we may read when the -t flag is specified. files are reset
		 * when we close them after copying. we reset the directories
		 * when we are done with their file tree (we also clean up at
		 * end in case we cut short a file tree traversal). However
		 * there is no way to reset access times on symlinks.
		 */
		switch(S_IFMT & arcn->sb.st_mode) {
		case S_IFDIR:
			arcn->type = PAX_DIR;
			if (!tflag)
				break;
			add_atdir(ftent->fts_path, arcn->sb.st_dev,
			    arcn->sb.st_ino, arcn->sb.st_mtime,
			    arcn->sb.st_atime);
			break;
		case S_IFCHR:
			arcn->type = PAX_CHR;
			break;
		case S_IFBLK:
			arcn->type = PAX_BLK;
			break;
		case S_IFREG:
			/*
			 * only regular files with have data to store on the
			 * archive. all others will store a zero length skip.
			 * the skip field is used by pax for actual data it has
			 * to read (or skip over).
			 */
			arcn->type = PAX_REG;
			arcn->skip = arcn->sb.st_size;
			break;
		case S_IFLNK:
			arcn->type = PAX_SLK;
			/*
			 * have to read the symlink path from the file
			 */
			if ((cnt = readlink(ftent->fts_path, arcn->ln_name,
			    PAXPATHLEN - 1)) < 0) {
				syswarn(1, errno, "Unable to read symlink %s",
				    ftent->fts_path);
				continue;
			}
			/*
			 * set link name length, watch out readlink does not
			 * always NUL terminate the link path
			 */
			arcn->ln_name[cnt] = '\0';
			arcn->ln_nlen = cnt;
			break;
		case S_IFSOCK:
			/*
			 * under BSD storing a socket is senseless but we will
			 * let the format specific write function make the
			 * decision of what to do with it.
			 */
			arcn->type = PAX_SCK;
			break;
		case S_IFIFO:
			arcn->type = PAX_FIF;
			break;
		}
		break;
	}

	/*
	 * copy file name, set file name length
	 */
	arcn->nlen = l_strncpy(arcn->name, ftent->fts_path, sizeof(arcn->name) - 1);
	arcn->name[arcn->nlen] = '\0';
	arcn->org_name = ftent->fts_path;
	return(0);
}
Beispiel #13
0
void knh_System_initPath(CTX ctx, knh_System_t *o)
{
	knh_DictMap_t *sysprops = DP(o)->props;
	knh_path_t phbuf, *ph = knh_path_open(ctx, NULL, ".", &phbuf);
	knh_bytes_t home = {{NULL}, 0}, user = {{NULL}, 0};

	// current working directory
	knh_ospath(ctx, ph);
	KNH_SETv(ctx, ctx->share->rootns->rpath, knh_path_newString(ctx, ph, 0));

	home.text = (const char*)knh_getenv("KONOHAHOME");
#if defined(K_KONOHAHOME)
	if(home.text == NULL) {
		home.text = K_KONOHAHOME;
	}
#endif
	if(home.text != NULL) {
		home.len = knh_strlen(home.text);
		SETPROP("konoha.home.path", new_T(home.text));
	}
#if defined(K_USING_WINDOWS)
	{
		char buf[FILEPATH_BUFSIZ];
		int bufsiz = FILEPATH_BUFSIZ;
		HMODULE h = LoadLibrary(NULL);
		GetModuleFileNameA(h, buf, bufsiz);
		ph = knh_path_open_(ctx, NULL, B(buf), &phbuf);
		SETPROP("konoha.bin.path", knh_path_newString(ctx, ph, 0));
		if(homepath == NULL) {
			knh_String_t *s;
			GetModuleFileNameA(h, buf, bufsiz);
			knh_path_reduce(ctx, ph, '/');
			s = knh_path_newString(ctx, ph);
			SETPROP("konoha.home.path", UPCAST(s));
			home = S_tobytes(shome);
		}
	}
#elif defined(K_USING_LINUX_)
	// @url(http://shinh.skr.jp/binary/b2con.html)
	// http://doc.trolltech.com/3.3/qapplication.html#applicationDirPath
	{
		char buf[FILEPATH_BUFSIZ];
		int bufsiz = FILEPATH_BUFSIZ;
		size_t size = readlink("/proc/self/exe", buf, bufsiz);
		ph = knh_path_open_(ctx, NULL, new_bytes2(buf, size), &phbuf);
		SETPROP("konoha.bin.path", knh_path_newString(ctx, ph, 0));
		if(home.text == NULL) {
			knh_String_t *s;
			knh_path_reduce(ctx, ph, '/');
			knh_path_reduce(ctx, ph, '/');
			knh_path_append(ctx, ph, 1/*isSep*/, "konoha");
			s = knh_path_newString(ctx, ph, 0/*hasScheme*/);
			SETPROP("konoha.home.path", UPCAST(s));
			home = S_tobytes(s);
		}
	}
#elif defined(K_USING_MACOSX_)
	ph = knh_path_open(ctx, NULL, _dyld_get_image_name(0), &phbuf);
	knh_ospath(ctx, ph);
	SETPROP("konoha.bin.path", knh_path_newString(ctx, ph, 0/*hasScheme*/));
	if(home.text == NULL) {
		knh_String_t *s;
		knh_path_reduce(ctx, ph, '/');
		knh_path_reduce(ctx, ph, '/');
		knh_path_append(ctx, ph, 1/*isSep*/, "konoha");
		s = knh_path_newString(ctx, ph, 0/*hasScheme*/);
		SETPROP("konoha.home.path", UPCAST(s));
		home = S_tobytes(s);
	}
#else
	home = STEXT("/opt/konoha");
	SETPROP("konoha.home.path", new_T("/opt/konoha"));
#endif
	DBG_ASSERT(home.utext != NULL);

	/* $konoha.package.path {$konoha.home.path}/package */
	knh_path_reset(ctx, ph, NULL, home);
	knh_path_append(ctx, ph, 1/*sep*/, "package");
	knh_path_append(ctx, ph, 1/*sep*/, LIBK_VERSION);
	SETPROP("konoha.package.path", knh_path_newString(ctx, ph, 0/*hasScheme*/));

	/* $konoha.script.path {$konoha.home.path}/script */
	knh_path_reset(ctx, ph, NULL, home);
	knh_path_append(ctx, ph, 1/*sep*/, "script");
	knh_path_append(ctx, ph, 1/*sep*/, LIBK_VERSION);
	SETPROP("konoha.script.path", knh_path_newString(ctx, ph, 0/*hasScheme*/));

#if defined(K_USING_WINDOWS)
	user.text = knh_getenv("USERPROFILE");
#else
	user.text = knh_getenv("HOME");
#endif
	if(user.text != NULL) {
		/* $user.path */
		user.len = knh_strlen(user.text);
		knh_path_reset(ctx, ph, NULL, user);
		knh_path_append(ctx, ph, 1/*sep*/, K_KONOHAFOLDER);
		SETPROP("user.path", knh_path_newString(ctx, ph, 0));
		knh_ospath(ctx, ph);
		knh_path_mkdir(ctx, ph);

		knh_path_reset(ctx, ph, NULL, user); /* user.package.path */
		knh_path_append(ctx, ph, 1/*sep*/, K_KONOHAFOLDER);
		knh_path_append(ctx, ph, 1/*sep*/, "package");
		knh_path_append(ctx, ph, 1/*sep*/, LIBK_VERSION);
		SETPROP("user.package.path", knh_path_newString(ctx, ph, 0));
	}
	knh_path_close(ctx, ph);
}
int getLocationsViafstab()
{
    FILE* fp;
    char line[512];
    int ret = 0;

    // In this case, we'll first get the partitions we care about (with labels)
    fp = fopen("/etc/recovery.fstab", "rt");
    if (fp == NULL)
    {
        LOGE("=> Unable to open /etc/recovery.fstab\n");
        return -1;
    }

    while (fgets(line, sizeof(line), fp) != NULL)
    {
        char mount[32], fstype[32], device[256];
        char* pDevice = device;

        if (line[0] != '/')     continue;
        sscanf(line + 1, "%s %s %s", mount, fstype, device);

        // Attempt to flip mounts until we find the block device
        char realDevice[256];
        memset(realDevice, 0, sizeof(realDevice));
        while (readlink(device, realDevice, sizeof(realDevice)) > 0)
        {
            strcpy(device, realDevice);
            memset(realDevice, 0, sizeof(realDevice));
        }

        if (device[0] != '/')   pDevice = NULL;
        setLocationData(mount, pDevice, pDevice, fstype, 0);
    }
    fclose(fp);

    // We can ignore the results of this call. But if it works, it at least helps get details
    getSizesViaPartitions();

    // Now, let's retrieve base partition sizes
    if (isEMMCdevice)
    {
        fp = __popen("fdisk -l /dev/block/mmcblk0","r");
        if (fp == NULL)
        {
            LOGE("=> Unable to retrieve partition sizes via fdisk\n");
            return -1;
        }
    
        while (fgets(line, sizeof(line), fp) != NULL)
        {
            char isBoot[64], device[64], blocks[2][16], *pSizeBlock;
            unsigned long long size = 0;
    
            if (line[0] != '/')     continue;
            sscanf(line, "%s %s %*s %s %s", device, isBoot, blocks[0], blocks[1]);
    

            if (isBoot[0] == '*')   pSizeBlock = blocks[1];
            else                    pSizeBlock = blocks[0];

            // If the block size isn't accurate, don't record it.
            if (pSizeBlock[strlen(pSizeBlock)-1] == '+')    pSizeBlock = NULL;

            // This could be NULL if we decided the size wasn't accurate
            if (pSizeBlock)
            {
                size = ((unsigned long long) atol(pSizeBlock)) * 1024ULL;
            }

            if (size && (setLocationData(NULL, device, NULL, NULL, size) == 0))
            {
//                LOGI("  Mount %s size: %d\n", device, size);
            }
        }
        fclose(fp);
    }

    return ret;
}
Beispiel #15
0
int main(int argc, char* argv[])
{
#ifdef HAVE_EXECINFO_H
    signal(SIGSEGV, crash_sig);
    signal(SIGABRT, crash_sig);
    signal(SIGPIPE, SIG_IGN);
#endif

#ifdef WIN32
    HANDLE localfd;
    WSADATA wsa;
    enum_device_t devs[MAX_DEVICE_COUNT];
#else
    int localfd;
#endif
    char cmd[1024];
    int remotefd;
    library_conf_t conf;
    int opt;
    struct in_addr a;

    struct option long_options[] = {
        { "conf", 1, NULL, 'c' },
        { NULL,   0, NULL,  0  }
    };
    char short_options[512] = {0};
    longopt2shortopt(long_options, sizeof(long_options) / sizeof(struct option), short_options);
#ifdef HAVE_SYSLOG_H
    openlog(argv[0], LOG_PERROR | LOG_CONS | LOG_PID, LOG_LOCAL0);
#endif

    qtun = calloc(sizeof(*qtun), 1);

#ifdef WIN32
    remotefd = -1;
    localfd = INVALID_HANDLE_VALUE;
#else
    localfd = remotefd = -1;
#endif
    {
        char path[MAX_PATH] = {0};
#ifdef WIN32
        strcpy(path, argv[0]);
#elif defined(__APPLE__)
        char tmp_path[sizeof(path)] = {0};
        uint32_t len = sizeof(path);
        if (_NSGetExecutablePath(tmp_path, &len) == -1) {
            perror("_NSGetExecutablePath");
            return 1;
        }
        if (readlink(tmp_path, path, sizeof(path)) == -1) {
            if (errno == EINVAL) strcpy(path, tmp_path);
            else {
                perror("readlink");
                return 1;
            }
        }
#else
        if (readlink("/proc/self/exe", path, sizeof(path)) == -1)
        {
            perror("readlink");
            return 1;
        }
#endif
        init_path(path);
    }
    conf_init(&conf);

    while ((opt = getopt_long(argc, argv, short_options, long_options, NULL)) != -1)
    {
        switch (opt)
        {
        case 'c':
            {
                char* path = realpath(optarg, NULL);
                if (path == NULL) {
                    perror("realpath");
                    return 1;
                }
                strcpy(conf.conf_file, path);
                free(path);
            }
            break;
        default:
            fprintf(stderr, "param error\n");
            return 1;
        }
    }

#ifdef WIN32
    {
        size_t count = enum_devices(devs);
        if (count == 0)
        {
            fprintf(stderr, "have no QTun Virtual Adapter\n");
            return 1;
        }
        else if (count == 1)
        {
            strcpy(conf.dev_symbol, devs[0].dev_path);
            strcpy(conf.dev_name, devs[0].dev_name);
        }
        else
        {
            size_t i;
            char str[20] = { 0 };
            int n = -1;
            printf("Have Adapters:\n");
            for (i = 0; i < count; ++i)
            {
                printf("%lu: %s\n", i + 1, devs[i].dev_name);
            }
            printf("Choose One[1]: ");
            while (n == -1)
            {
                if (str[0] == '\n' && str[1] == 0) n = 1;
                else
                {
                    if (!is_int(str, sizeof(str))) continue;
                    n = atoi(str);
                    if (n < 1 || n > (int)count)
                    {
                        fprintf(stderr, "Invalid Number must >= 1 and <= %lu\n", count);
                        n = -1;
                        continue;
                    }
                }
            }
            strcpy(conf.dev_symbol, devs[n].dev_path);
            strcpy(conf.dev_name, devs[n].dev_name);
        }
    }
#endif
    
    init_lua();
    show_logo();
    script_load_config(qtun->lua, &conf, conf.conf_file);

#ifdef WIN32
    if (strlen(conf.dev_symbol) == 0)
    {
        fprintf(stderr, "Missing param [-e] or [--device]\n");
        return 1;
    }
#endif

#ifdef WIN32
    localfd = tun_open(conf.dev_symbol);
    if (localfd == INVALID_HANDLE_VALUE) return 1;
    fprintf(stdout, "%s opened\n", conf.dev_name);
#else
    memset(qtun->dev_name, 0, IFNAMSIZ);
    localfd = tun_open(qtun->dev_name);
    if (localfd == -1) return 1;
    syslog(LOG_INFO, "%s opened\n", qtun->dev_name);
#endif
    a.s_addr = conf.localip;

#ifdef WIN32
    WSAStartup(MAKEWORD(2, 2), &wsa);
#endif
    if (strlen(conf.server) == 0)
    {
        if (conf.netmask == 0 || conf.netmask > 31)
        {
#ifdef WIN32
            WSACleanup();
#endif

            fprintf(stderr, "netmask must > 0 and <= 31\n");
            return 1;
        }
        library_init(conf);
        if (conf.localip == 0)
        {
            fprintf(stderr, "localip is zero\n");
            return 1;
        }
        if (strlen(conf.signature_file) == 0) {
            fprintf(stderr, "missing signature file\n");
            return 1;
        }
        qtun->is_server = 1;
        remotefd = bind_and_listen(conf.server_port);
        if (remotefd == -1)
        {
#ifdef WIN32
            WSACleanup();
#endif
            return 1;
        }
#ifdef WIN32
        {
            a.s_addr = conf.localip;
            sprintf(cmd, "netsh interface ip set address name=\"%s\" static %s %s", conf.dev_name, inet_ntoa(a), STR_LEN2MASK(conf.netmask));
            SYSTEM_EXIT(cmd);
        }
#elif defined(__APPLE__)
        {
            sprintf(cmd, "ifconfig %s %s/%u up", qtun->dev_name, inet_ntoa(a), conf.netmask);
            SYSTEM_EXIT(cmd);
            a.s_addr = conf.localip & LEN2MASK(conf.netmask);
            sprintf(cmd, "route add -net %s/%u %s", inet_ntoa(a), conf.netmask, inet_ntoa(a));
            SYSTEM_EXIT(cmd);
        }
#else
        {
            sprintf(cmd, "ifconfig %s %s/%u up", qtun->dev_name, inet_ntoa(a), conf.netmask);
            SYSTEM_EXIT(cmd);
            a.s_addr = conf.localip & LEN2MASK(conf.netmask);
            sprintf(cmd, "route add -net %s/%u dev %s", inet_ntoa(a), conf.netmask, qtun->dev_name);
            SYSTEM_EXIT(cmd);
        }
#endif
        server_loop(remotefd, localfd);
    }
    else
    {
#ifdef unix
        unsigned char mask;
#endif
        int inited = 0;
        library_init(conf);
        qtun->is_server = 0;
        while (1)
        {
            remotefd = connect_server(conf.server, conf.server_port);
            if (remotefd == -1)
            {
                SLEEP(5);
                continue;
            }
            a.s_addr = qtun->localip;
            if (qtun->localip == 0)
            {
                fprintf(stderr, "localip is zero\n");
                return 1;
            }
            if (strlen(conf.signature_file) == 0) {
                fprintf(stderr, "missing signature file\n");
                return 1;
            }
            if (!inited)
            {
#ifdef WIN32
                {
                    sprintf(cmd, "netsh interface ip set address name=\"%s\" static %s %s", conf.dev_name, inet_ntoa(a), STR_LEN2MASK(conf.netmask));
                    SYSTEM_EXIT(cmd);
                }
#elif defined(__APPLE__)
                {
                    char ip1[16], ip2[16];
                    a.s_addr = qtun->localip;
                    strcpy(ip1, inet_ntoa(a));
                    a.s_addr = qtun->client.local_ip;
                    strcpy(ip2, inet_ntoa(a));
                    sprintf(cmd, "ifconfig %s inet %s %s up", qtun->dev_name, ip1, ip2);
                    SYSTEM_EXIT(cmd);
                    mask = netmask();
                    a.s_addr = qtun->localip & LEN2MASK(mask);
                    sprintf(cmd, "route add -net %s/%u %s", inet_ntoa(a), mask, ip2);
                    SYSTEM_EXIT(cmd);
                }
#else
                {
                    sprintf(cmd, "ifconfig %s %s up", qtun->dev_name, inet_ntoa(a));
                    SYSTEM_EXIT(cmd);
                    mask = netmask();
                    a.s_addr = qtun->localip & LEN2MASK(mask);
                    sprintf(cmd, "route add -net %s/%u dev %s", inet_ntoa(a), mask, qtun->dev_name);
                    SYSTEM_EXIT(cmd);
                }
#endif
                inited = 1;
            }
            client_loop(remotefd, localfd);
            close(remotefd);
            SYSLOG(LOG_WARNING, "retry");
        }
    }
#ifdef WIN32
    WSACleanup();
#endif

#ifdef HAVE_SYSLOG_H
    closelog();
#endif

    library_free();
    return 0;
}
Beispiel #16
0
/* This is the routine that constructs the filesystem image.  */
int
mkfs(FILE *fs, const char *path, int ino, int parent, int depth)
{
  struct dirent *dir_entry;
  DIR *dir;
  struct stat st;
  struct jffs_file f;
  int name_len;
  int pos = 0;
  int new_ino = ino;
  char *filename;
  int path_len = strlen(path);
  __u16 chksum;

  if (verbose >= 2)
  {
    fprintf(stderr, "***mkfs(): path: \"%s\"\r\n", path);
  }

  if (!(dir = opendir(path)))
  {
    perror("opendir");
    fprintf(stderr, "mkfs(): opendir() failed! (%s)\n", path);
    exit(1);
  }

  while ((dir_entry = readdir(dir)))
  {
    if (verbose >= 2)
    {
     fprintf(stderr, "mkfs(): name: %s\n", dir_entry->d_name);
    }
    name_len = strlen(dir_entry->d_name);

    if (((name_len == 1)
         && (dir_entry->d_name[0] == '.'))
        || ((name_len == 2)
            && (dir_entry->d_name[0] == '.')
            && (dir_entry->d_name[1] == '.')))
    {
      continue;
    }

    if (!(filename = (char *)alloca(path_len + name_len + 1)))
    {
      fprintf(stderr, "mkfs(): Allocation failed!\n");
      exit(0);
    }
    strcpy(filename, path);
    strcat(filename, dir_entry->d_name);

    if (verbose >= 2)
    {
      fprintf(stderr, "mkfs(): filename: %s\n", filename);
    }

    if (lstat(filename, &st) < 0)
    {
      perror("lstat");
      exit(1);
    }

    if (verbose >= 2)
    {
      fprintf(stderr, "mkfs(): filename: \"%s\", ino: %d, parent: %d\n",
              filename, new_ino, parent);
    }

    f.inode.magic = JFFS_MAGIC;
    f.inode.ino = new_ino;
    f.inode.pino = parent;
    f.inode.version = 1;
    f.inode.mode = st.st_mode;
    f.inode.uid = st.st_uid;
    f.inode.gid = st.st_gid;
    f.inode.atime = st.st_atime;
    f.inode.mtime = st.st_mtime;
    f.inode.ctime = st.st_ctime;
    f.inode.dsize = 0;
    f.inode.rsize = 0;
    f.inode.nsize = name_len;
    /*f.inode.nlink = st.st_nlink;*/
    f.inode.nlink = 1;
    f.inode.spare = 0;
    f.inode.rename = 0;
    f.inode.deleted = 0;
    f.inode.accurate = 0;
    f.inode.dchksum = 0;
    f.inode.nchksum = 0;
    f.inode.chksum = 0;
    if (dir_entry->d_name)
    {
      f.name = strdup(dir_entry->d_name);
    }
    else
    {
      f.name = 0;
    }

  repeat:
    f.inode.offset = pos;
    f.data = 0;
    f.inode.accurate = 0;
    if (S_ISREG(st.st_mode) && st.st_size)
    {
      if (st.st_size - pos < MAX_CHUNK_SIZE)
      {
	f.inode.dsize = st.st_size - pos;
      }
      else
      {
	f.inode.dsize = MAX_CHUNK_SIZE;
      }

      read_data(&f, path, pos);
      pos += f.inode.dsize;
    }
    else if (S_ISLNK(st.st_mode))
    {
      int linklen;
      unsigned char *linkdata = (unsigned char *)malloc(1000);
      if (!linkdata)
      {
        fprintf(stderr, "mkfs(): malloc() failed! (linkdata)\n");
        exit(1);
      }
      if ((linklen = readlink(filename, linkdata, 1000)) < 0)
      {
        free(linkdata);
        fprintf(stderr, "mkfs(): readlink() failed! f.name = \"%s\"\n",
                f.name);
        exit(1);
      }

      f.inode.dsize = linklen;
      f.data = linkdata;
      f.data[linklen] = '\0';
    }
    else if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode))
    {
      f.inode.dsize = sizeof(st.st_rdev) / 4;
    }

    f.inode.chksum = 0;
    if (!S_ISBLK(st.st_mode) && !S_ISCHR(st.st_mode))
    {
      f.inode.dchksum = jffs_checksum((void *)f.data, f.inode.dsize);
    }
    else
    {
      f.inode.dchksum
	= jffs_checksum((void *)&st.st_rdev, sizeof(st.st_rdev) / 4);
    }

    f.inode.nchksum = jffs_checksum((void *)f.name, f.inode.nsize);
	jffs_swap_inode(&f.inode);
    chksum = jffs_checksum((void *)&f.inode, sizeof(struct jffs_raw_inode));
	jffs_swap_inode(&f.inode);
    f.inode.chksum = chksum;
    f.inode.accurate = 0xff;

    write_file(&f, fs, st);
    if (S_ISREG(st.st_mode) && st.st_size)
    {
      if (pos < st.st_size)
      {
	f.inode.version++;
	goto repeat;
      }
    }

    new_ino++;
    pos = 0;
    if (verbose >= 1)
    {
      jffs_print_trace(f.name, depth);
    }
    if (verbose >= 2)
    {
      jffs_print_raw_inode(&f.inode);
    }

    if (S_ISDIR(st.st_mode))
    {
      char *new_path;

      if (!(new_path = (char *)alloca(strlen(path) + name_len + 1 + 1)))
      {
        fprintf(stderr, "mkfs(): alloca() failed! (new_path)\n");
        exit(1);
      }
      strcpy(new_path, path);
      strncat(new_path, f.name, f.inode.nsize);
      strcat(new_path, "/");

      if (verbose >= 2)
      {
        fprintf(stderr, "mkfs(): new_path: \"%s\"\n", new_path);
      }
      new_ino = mkfs(fs, new_path, new_ino, new_ino - 1, depth + 1);
    }
    if (f.name)
    {
      free(f.name);
    }
    if (f.data)
    {
      free(f.data);
    }
  }

  closedir(dir);
  return new_ino;
}
Beispiel #17
0
/*
 * Return the real path (i.e., absolute path, with symlinks resolved
 * and extra slashes removed) equivalent to the specified path.  (If
 * you want an absolute path but don't mind links, use
 * absolute_path().)  The return value is a pointer to a static
 * buffer.
 *
 * The input and all intermediate paths must be shorter than MAX_PATH.
 * The directory part of path (i.e., everything up to the last
 * dir_sep) must denote a valid, existing directory, but the last
 * component need not exist.  If die_on_error is set, then die with an
 * informative error message if there is a problem.  Otherwise, return
 * NULL on errors (without generating any output).
 *
 * If path is our buffer, then return path, as it's already what the
 * user wants.
 */
static const char *real_path_internal(const char *path, int die_on_error)
{
	static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
	char *retval = NULL;

	/*
	 * If we have to temporarily chdir(), store the original CWD
	 * here so that we can chdir() back to it at the end of the
	 * function:
	 */
	char cwd[1024] = "";

	int buf_index = 1;

	int depth = MAXDEPTH;
	char *last_elem = NULL;
	struct stat st;

	/* We've already done it */
	if (path == buf || path == next_buf)
		return path;

	if (!*path) {
		if (die_on_error)
			die("The empty string is not a valid path");
		else
			goto error_out;
	}

	if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX) {
		if (die_on_error)
			die("Too long path: %.*s", 60, path);
		else
			goto error_out;
	}

	while (depth--) {
		if (!is_directory(buf)) {
			char *last_slash = find_last_dir_sep(buf);
			if (last_slash) {
				last_elem = xstrdup(last_slash + 1);
				last_slash[1] = '\0';
			} else {
				last_elem = xstrdup(buf);
				*buf = '\0';
			}
		}

		if (*buf) {
			if (!*cwd && !getcwd(cwd, sizeof(cwd))) {
				if (die_on_error)
					die_errno("Could not get current working directory");
				else
					goto error_out;
			}

			if (chdir(buf)) {
				if (die_on_error)
					die_errno("Could not switch to '%s'", buf);
				else
					goto error_out;
			}
		}
		if (!getcwd(buf, PATH_MAX)) {
			if (die_on_error)
				die_errno("Could not get current working directory");
			else
				goto error_out;
		}

		if (last_elem) {
			size_t len = strlen(buf);
			if (len + strlen(last_elem) + 2 > PATH_MAX) {
				if (die_on_error)
					die("Too long path name: '%s/%s'",
					    buf, last_elem);
				else
					goto error_out;
			}
			if (len && !is_dir_sep(buf[len-1]))
				buf[len++] = '/';
			strcpy(buf + len, last_elem);
			free(last_elem);
			last_elem = NULL;
		}

		if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
			ssize_t len = readlink(buf, next_buf, PATH_MAX);
			if (len < 0) {
				if (die_on_error)
					die_errno("Invalid symlink '%s'", buf);
				else
					goto error_out;
			}
			if (PATH_MAX <= len) {
				if (die_on_error)
					die("symbolic link too long: %s", buf);
				else
					goto error_out;
			}
			next_buf[len] = '\0';
			buf = next_buf;
			buf_index = 1 - buf_index;
			next_buf = bufs[buf_index];
		} else
			break;
	}

	retval = buf;
error_out:
	free(last_elem);
	if (*cwd && chdir(cwd))
		die_errno ("Could not change back to '%s'", cwd);

	return retval;
}
Beispiel #18
0
int
getlock(char *name, struct passwd *pw)
{
	struct stat sb, fsb;
	int lfd=-1;
	char buf[8*1024];
	int tries = 0;

	(void)snprintf(lpath, sizeof lpath, "%s/%s.lock",
	    _PATH_MAILDIR, name);

	if (stat(_PATH_MAILDIR, &sb) != -1 &&
	    (sb.st_mode & S_IWOTH) == S_IWOTH) {
		/*
		 * We have a writeable spool, deal with it as
		 * securely as possible.
		 */
		time_t ctim = -1;

		seteuid(pw->pw_uid);
		if (lstat(lpath, &sb) != -1)
			ctim = sb.st_ctime;
		while (1) {
			/*
			 * Deal with existing user.lock files
			 * or directories or symbolic links that
			 * should not be here.
			 */
			if (readlink(lpath, buf, sizeof buf-1) != -1) {
				if (lstat(lpath, &sb) != -1 &&
				    S_ISLNK(sb.st_mode)) {
					seteuid(sb.st_uid);
					unlink(lpath);
					seteuid(pw->pw_uid);
				}
				goto again;
			}
			if ((lfd = open(lpath, O_CREAT|O_WRONLY|O_EXCL|O_EXLOCK,
			    S_IRUSR|S_IWUSR)) != -1)
				break;
again:
			if (tries > 10) {
				merr(NOTFATAL, "%s: %s", lpath,
				    strerror(errno));
				seteuid(0);
				return(-1);
			}
			if (tries > 9 &&
			    (lfd = open(lpath, O_WRONLY|O_EXLOCK, 0)) != -1) {
				if (fstat(lfd, &fsb) != -1 &&
				    lstat(lpath, &sb) != -1) {
					if (fsb.st_dev == sb.st_dev &&
					    fsb.st_ino == sb.st_ino &&
					    ctim == fsb.st_ctime ) {
						seteuid(fsb.st_uid);
						baditem(lpath);
						seteuid(pw->pw_uid);
					}
				}
			}
			sleep(1U << tries);
			tries++;
			continue;
		}
		seteuid(0);
	} else {
		/*
		 * Only root can write the spool directory.
		 */
		while (1) {
			if ((lfd = open(lpath, O_CREAT|O_WRONLY|O_EXCL,
			    S_IRUSR|S_IWUSR)) != -1)
				break;
			if (tries > 9) {
				merr(NOTFATAL, "%s: %s", lpath, strerror(errno));
				return(-1);
			}
			sleep(1U << tries);
			tries++;
		}
	}
	return(lfd);
}
Beispiel #19
0
int getdirlist(session_t *pses, int opt)
{
    DIR *dir = opendir(".");
    if(dir == NULL)
        return -1;

    struct dirent *dt;
    struct stat stbuf;
    while((dt = readdir(dir)) != NULL)
    {
        if(lstat(dt->d_name, &stbuf) < 0)
        {
            //文件查看失败
            continue;
        }

        //过滤一些文件夹
        if(dt->d_name[0] == '.')
            continue;

        char sendbuf[1024] = {0};
        int index = 0;

        //是否获取详细信息
        if(opt == 1)
        {
            //获取文件属性
            char perms[] = "----------";
            mode_t mode = stbuf.st_mode;
            switch(mode & S_IFMT)
            {
                case S_IFREG:
                    perms[0] = '-';
                    break;
                case S_IFDIR:
                    perms[0] = 'd';
                    break;
                case S_IFLNK:
                    perms[0] = 'l';
                    break;
                case S_IFIFO:
                    perms[0] = 'p';
                    break;
                case S_IFSOCK:
                    perms[0] = 's';
                    break;
                case S_IFCHR:
                    perms[0] = 'c';
                    break;
                case S_IFBLK:
                    perms[0] = 'b';
                    break;
                default:
                    perms[0] = '?';
                    break;
            }

            if(mode & S_IRUSR)
            {
                perms[1] = 'r';
            }
            if(mode & S_IWUSR)
            {
                perms[2] = 'w';
            }
            if(mode & S_IXUSR)
            {
                perms[3] = 'x';
            }

            if(mode & S_IRGRP)
            {
                perms[4] = 'r';
            }
            if(mode & S_IWGRP)
            {
                perms[5] = 'w';
            }
            if(mode & S_IXGRP)
            {
                perms[6] = 'x';
            }

            if(mode & S_IROTH)
            {
                perms[7] = 'r';
            }
            if(mode & S_IWOTH)
            {
                perms[8] = 'w';
            }
            if(mode & S_IXOTH)
            {
                perms[9] = 'x';
            }

            //特殊权限位
            if(mode & S_ISUID)
            {
                perms[3] = (perms[3] == 'x') ? 's' : 'S';
            }
            if(mode & S_ISGID)
            {
                perms[6] = (perms[3] == 'x') ? 's' : 'S';
            }
            if(mode & S_ISVTX)
            {
                perms[9] = (perms[3] == 'x') ? 't' : 'T';
            }

            //硬连接数,文件大小
            index += sprintf(sendbuf, "%s ",perms);
            index += sprintf(sendbuf + index, "%2d %4d %4d",(int)stbuf.st_nlink, stbuf.st_uid, stbuf.st_gid);

            index += sprintf(sendbuf + index,  "%8lu  ", (unsigned long)stbuf.st_size);

            //格式化文件时间
            const char *p_data_format = "%b %e %H:%M";
            struct timeval tv;
            gettimeofday(&tv, NULL);    //获取当前系统时间
            time_t local_time = tv.tv_sec;
            if((stbuf.st_mtime > local_time) || ((local_time - stbuf.st_mtime) > 60*60*24*182))
            {
                p_data_format = "%b %e %Y";
            }

            char datebuf[64] = {0};
            struct tm *p_tm = localtime(&local_time);
            strftime(datebuf, sizeof(datebuf), p_data_format, p_tm);

            index += sprintf(sendbuf + index,  "%s ", datebuf);
        }
        //获取文件名
        if(S_ISLNK(stbuf.st_mode))  //判断是否是连接文件
        {
            char temp[1024] = {0};
            readlink(dt->d_name, temp, sizeof(temp));
            sprintf(sendbuf + index, "%s -> %s\r\n", dt->d_name,temp);
        }
        else
        {
            sprintf(sendbuf + index, "%s\r\n", dt->d_name);
        }

        //发送给客户端
        if(writen(pses->data_fd, sendbuf, strlen(sendbuf)) < 0)
            handle_error("writen");
    }

    closedir(dir);
    return 0;
}
Beispiel #20
0
static int get_dev_mtd(const char *fdt_flash_path, char **mtd_path)
{
	struct dirent **namelist;
	char fdt_node_path[PATH_MAX];
	int count, i, rc, fd;
	bool done;

	if (!fdt_flash_path)
		return -1;

	fd = open(fdt_flash_path, O_RDONLY);
	if (fd == -1) {
		fprintf(stderr, "Couldn't open '%s' FDT attribute to determine which flash device to use\n",
				fdt_flash_path);
		fprintf(stderr, "Is your skiboot new enough to expose the flash through the device tree?\n");
		hint_root();
		return -1;
	}

	rc = read(fd, fdt_node_path, sizeof(fdt_node_path));
	close(fd);
	if (rc == -1) {
		fprintf(stderr, "Couldn't read flash FDT node from '%s'\n", fdt_flash_path);
		hint_root();
		return -1;
	}

	count = scandir(SYSFS_MTD_PATH, &namelist, NULL, alphasort);
	if (count == -1) {
		fprintf(stderr, "Couldn't scan '%s' for MTD\n", SYSFS_MTD_PATH);
		hint_root();
		return -1;
	}

	rc = 0;
	done = false;
	for (i = 0; i < count; i++) {
		struct dirent *dirent;
		char *dev_path;
		char fdt_node_path_tmp[PATH_MAX];

		dirent = namelist[i];

		/*
		 * The call to asprintf must happen last as when it succeeds it
		 * will allocate dev_path
		 */
		if (dirent->d_name[0] == '.' || rc || done ||
			asprintf(&dev_path, "%s/%s/device/of_node", SYSFS_MTD_PATH, dirent->d_name) < 0) {
			free(namelist[i]);
			continue;
		}

		rc = readlink(dev_path, fdt_node_path_tmp, sizeof(fdt_node_path_tmp) - 1);
		free(dev_path);
		if (rc == -1) {
			/*
			 * This might fail because it could not exist if the system has flash
			 * devices that present as mtd but don't have corresponding FDT
			 * nodes, just continue silently.
			 */
			free(namelist[i]);
			/* Should still try the next dir so reset rc */
			rc = 0;
			continue;
		}
		fdt_node_path_tmp[rc] = '\0';

		if (strstr(fdt_node_path_tmp, fdt_node_path)) {
			uint32_t flags, size;

			/*
			 * size and flags could perhaps have be gotten another way but this
			 * method is super unlikely to fail so it will do.
			 */

			/* Check to see if device is writeable */
			rc = get_dev_attr(dirent->d_name, "flags", &flags);
			if (rc) {
				free(namelist[i]);
				continue;
			}

			/* Get the size of the mtd device while we're at it */
			rc = get_dev_attr(dirent->d_name, "size", &size);
			if (rc) {
				free(namelist[i]);
				continue;
			}

			rc = asprintf(&dev_path, "/dev/%s", dirent->d_name);
			if (rc < 0) {
				free(namelist[i]);
				continue;
			}
			rc = 0;
			*mtd_path = dev_path;
			done = true;
		}
		free(namelist[i]);
	}
	free(namelist);

	if (!done) {
		fprintf(stderr, "Couldn't find '%s' corresponding MTD\n", fdt_flash_path);
		fprintf(stderr, "Is your kernel new enough to expose MTD?\n");
	}

	/* explicit negative value so as to not return a libflash code */
	return done ? rc : -1;
}
Beispiel #21
0
static void add_sound_files(GtkWidget *vbox, DIR *dp)
{
    int i = 1, len;
    struct dirent *ep;
    struct stat st;
    char *file, *p;

    enable_sound_button = gtk_check_button_new_with_label("Enable sound");
    g_signal_connect (G_OBJECT (enable_sound_button), "toggled",
                      G_CALLBACK (enable_sound_button_toggled), NULL);
    gtk_box_pack_start (GTK_BOX (vbox), enable_sound_button, FALSE, FALSE, 10);

    cur_file_label = gtk_label_new("");
    gtk_misc_set_alignment(GTK_MISC(cur_file_label), 0.0, 0.5);

    GtkWidget *hbox = gtk_hbox_new(FALSE, 0);

    file_list =  gtk_combo_box_new_text();

    change_button = gtk_button_new_with_label("Change");
    gtk_widget_set_sensitive(change_button, FALSE);
    g_signal_connect (G_OBJECT (change_button), "clicked", G_CALLBACK (change_button_clicked), NULL);

    gtk_combo_box_append_text (GTK_COMBO_BOX(file_list), "-- please select --");
    gtk_combo_box_set_active (GTK_COMBO_BOX(file_list), 0);

    char buf[256], buf1[256];
    /* sound.py */
    while ((ep = readdir (dp))) {
        if (ep->d_type != DT_LNK && ep->d_type != DT_REG)
            continue;

        p = strstr(ep->d_name, ".py");
        if (! p || strlen(p) != 3)
            continue;

        file = ep->d_name;

        snprintf(buf, sizeof(buf), "%s/%s", OMGPS_SOUND_TOP_DIR, file);

        if (ep->d_type == DT_LNK) {
            len = readlink(buf, buf1, sizeof(buf1));
            if (len <= 0 || len == sizeof(buf1))
                continue;
            buf1[len] = '\0';
            if (stat(buf1, &st) != 0 || ! S_ISREG(st.st_mode))
                continue;
        } else if (ep->d_type != DT_REG) {
            continue;
        }

        gtk_combo_box_append_text (GTK_COMBO_BOX(file_list), file);

        snprintf(buf1, sizeof(buf), "%s/%s", g_context.config_dir, file);
        symlink(buf, buf1);

        gboolean is = (g_cfg->last_sound_file && strcmp(g_cfg->last_sound_file, file) == 0);
        if (is) {
            gtk_label_set_text(GTK_LABEL(cur_file_label), file);
            gtk_combo_box_set_active (GTK_COMBO_BOX(file_list), i);
            last_idx = i;
        }
        ++i;
    }
    closedir (dp);


    /* NOTE: gtk_combo_box_append_text() triggers "changed" event */
    g_signal_connect (G_OBJECT (file_list), "changed", G_CALLBACK (file_list_changed), NULL);

    GtkWidget *hbox0 = gtk_hbox_new(FALSE, 0);

    GtkWidget *label0 = gtk_label_new("Current file: ");
    gtk_misc_set_alignment(GTK_MISC(label0), 0.0, 0.5);

    gtk_box_pack_start (GTK_BOX (hbox0), label0, FALSE, FALSE, 3);
    gtk_box_pack_start (GTK_BOX (hbox0), cur_file_label, TRUE, TRUE, 0);

    gtk_box_pack_start(GTK_BOX(hbox), file_list, TRUE, TRUE, 3);
    gtk_box_pack_start(GTK_BOX(hbox), change_button, FALSE, FALSE, 0);

    gtk_box_pack_start (GTK_BOX (vbox), hbox0, FALSE, FALSE, 5);

    gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 5);
}
static u32 build_default_directory_structure(const char *dir_path,
					     struct selabel_handle *sehnd)
{
	u32 inode;
	u32 root_inode;
	struct dentry dentries = {
			.filename = "lost+found",
			.file_type = EXT4_FT_DIR,
			.mode = S_IRWXU,
			.uid = 0,
			.gid = 0,
			.mtime = 0,
	};
	root_inode = make_directory(0, 1, &dentries, 1);
	inode = make_directory(root_inode, 0, NULL, 0);
	*dentries.inode = inode;
	inode_set_permissions(inode, dentries.mode,
		dentries.uid, dentries.gid, dentries.mtime);

#ifndef USE_MINGW
	if (sehnd) {
		char *path = NULL;
		char *secontext = NULL;

		asprintf(&path, "%slost+found", dir_path);
		if (selabel_lookup(sehnd, &secontext, path, S_IFDIR) < 0) {
			error("cannot lookup security context for %s", path);
		} else {
			inode_set_selinux(inode, secontext);
			freecon(secontext);
		}
		free(path);
	}
#endif

	return root_inode;
}

#ifndef USE_MINGW
/* Read a local directory and create the same tree in the generated filesystem.
   Calls itself recursively with each directory in the given directory.
   full_path is an absolute or relative path, with a trailing slash, to the
   directory on disk that should be copied, or NULL if this is a directory
   that does not exist on disk (e.g. lost+found).
   dir_path is an absolute path, with trailing slash, to the same directory
   if the image were mounted at the specified mount point */
static u32 build_directory_structure(const char *full_path, const char *dir_path, const char *target_out_path,
		u32 dir_inode, fs_config_func_t fs_config_func,
		struct selabel_handle *sehnd, int verbose, time_t fixed_time)
{
	int entries = 0;
	struct dentry *dentries;
	struct dirent **namelist = NULL;
	struct stat stat;
	int ret;
	int i;
	u32 inode;
	u32 entry_inode;
	u32 dirs = 0;
	bool needs_lost_and_found = false;

	if (full_path) {
		entries = scandir(full_path, &namelist, filter_dot, (void*)alphasort);
		if (entries < 0) {
#ifdef __GLIBC__
			/* The scandir function implemented in glibc has a bug that makes it
			   erroneously fail with ENOMEM under certain circumstances.
			   As a workaround we can retry the scandir call with the same arguments.
			   GLIBC BZ: https://sourceware.org/bugzilla/show_bug.cgi?id=17804 */
			if (errno == ENOMEM)
				entries = scandir(full_path, &namelist, filter_dot, (void*)alphasort);
#endif
			if (entries < 0) {
				error_errno("scandir");
				return EXT4_ALLOCATE_FAILED;
			}
		}
	}

	if (dir_inode == 0) {
		/* root directory, check if lost+found already exists */
		for (i = 0; i < entries; i++)
			if (strcmp(namelist[i]->d_name, "lost+found") == 0)
				break;
		if (i == entries)
			needs_lost_and_found = true;
	}

	dentries = calloc(entries, sizeof(struct dentry));
	if (dentries == NULL)
		critical_error_errno("malloc");

	for (i = 0; i < entries; i++) {
		dentries[i].filename = strdup(namelist[i]->d_name);
		if (dentries[i].filename == NULL)
			critical_error_errno("strdup");

		asprintf(&dentries[i].path, "%s%s", dir_path, namelist[i]->d_name);
		asprintf(&dentries[i].full_path, "%s%s", full_path, namelist[i]->d_name);

		free(namelist[i]);

		ret = lstat(dentries[i].full_path, &stat);
		if (ret < 0) {
			error_errno("lstat");
			i--;
			entries--;
			continue;
		}

		dentries[i].size = stat.st_size;
		dentries[i].mode = stat.st_mode & (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO);
		if (fixed_time == -1) {
			dentries[i].mtime = stat.st_mtime;
		} else {
			dentries[i].mtime = fixed_time;
		}
		uint64_t capabilities;
		if (fs_config_func != NULL) {
#ifdef ANDROID
			unsigned int mode = 0;
			unsigned int uid = 0;
			unsigned int gid = 0;
			int dir = S_ISDIR(stat.st_mode);
			fs_config_func(dentries[i].path, dir, target_out_path, &uid, &gid, &mode, &capabilities);
			dentries[i].mode = mode;
			dentries[i].uid = uid;
			dentries[i].gid = gid;
			dentries[i].capabilities = capabilities;
#else
			error("can't set android permissions - built without android support");
#endif
		}
#ifndef USE_MINGW
		if (sehnd) {
			if (selabel_lookup(sehnd, &dentries[i].secon, dentries[i].path, stat.st_mode) < 0) {
				error("cannot lookup security context for %s", dentries[i].path);
			}

			if (dentries[i].secon && verbose)
				printf("Labeling %s as %s\n", dentries[i].path, dentries[i].secon);
		}
#endif

		if (S_ISREG(stat.st_mode)) {
			dentries[i].file_type = EXT4_FT_REG_FILE;
		} else if (S_ISDIR(stat.st_mode)) {
			dentries[i].file_type = EXT4_FT_DIR;
			dirs++;
		} else if (S_ISCHR(stat.st_mode)) {
			dentries[i].file_type = EXT4_FT_CHRDEV;
		} else if (S_ISBLK(stat.st_mode)) {
			dentries[i].file_type = EXT4_FT_BLKDEV;
		} else if (S_ISFIFO(stat.st_mode)) {
			dentries[i].file_type = EXT4_FT_FIFO;
		} else if (S_ISSOCK(stat.st_mode)) {
			dentries[i].file_type = EXT4_FT_SOCK;
		} else if (S_ISLNK(stat.st_mode)) {
			dentries[i].file_type = EXT4_FT_SYMLINK;
			dentries[i].link = calloc(info.block_size, 1);
			readlink(dentries[i].full_path, dentries[i].link, info.block_size - 1);
		} else {
			error("unknown file type on %s", dentries[i].path);
			i--;
			entries--;
		}
	}
	free(namelist);

	if (needs_lost_and_found) {
		/* insert a lost+found directory at the beginning of the dentries */
		struct dentry *tmp = calloc(entries + 1, sizeof(struct dentry));
		memset(tmp, 0, sizeof(struct dentry));
		memcpy(tmp + 1, dentries, entries * sizeof(struct dentry));
		dentries = tmp;

		dentries[0].filename = strdup("lost+found");
		asprintf(&dentries[0].path, "%slost+found", dir_path);
		dentries[0].full_path = NULL;
		dentries[0].size = 0;
		dentries[0].mode = S_IRWXU;
		dentries[0].file_type = EXT4_FT_DIR;
		dentries[0].uid = 0;
		dentries[0].gid = 0;
		if (sehnd) {
			if (selabel_lookup(sehnd, &dentries[0].secon, dentries[0].path, dentries[0].mode) < 0)
				error("cannot lookup security context for %s", dentries[0].path);
		}
		entries++;
		dirs++;
	}

	inode = make_directory(dir_inode, entries, dentries, dirs);

	for (i = 0; i < entries; i++) {
		if (dentries[i].file_type == EXT4_FT_REG_FILE) {
			entry_inode = make_file(dentries[i].full_path, dentries[i].size);
		} else if (dentries[i].file_type == EXT4_FT_DIR) {
			char *subdir_full_path = NULL;
			char *subdir_dir_path;
			if (dentries[i].full_path) {
				ret = asprintf(&subdir_full_path, "%s/", dentries[i].full_path);
				if (ret < 0)
					critical_error_errno("asprintf");
			}
			ret = asprintf(&subdir_dir_path, "%s/", dentries[i].path);
			if (ret < 0)
				critical_error_errno("asprintf");
			entry_inode = build_directory_structure(subdir_full_path, subdir_dir_path, target_out_path,
					inode, fs_config_func, sehnd, verbose, fixed_time);
			free(subdir_full_path);
			free(subdir_dir_path);
		} else if (dentries[i].file_type == EXT4_FT_SYMLINK) {
			entry_inode = make_link(dentries[i].link);
		} else {
			error("unknown file type on %s", dentries[i].path);
			entry_inode = 0;
		}
		*dentries[i].inode = entry_inode;

		ret = inode_set_permissions(entry_inode, dentries[i].mode,
			dentries[i].uid, dentries[i].gid,
			dentries[i].mtime);
		if (ret)
			error("failed to set permissions on %s\n", dentries[i].path);

		/*
		 * It's important to call inode_set_selinux() before
		 * inode_set_capabilities(). Extended attributes need to
		 * be stored sorted order, and we guarantee this by making
		 * the calls in the proper order.
		 * Please see xattr_assert_sane() in contents.c
		 */
		ret = inode_set_selinux(entry_inode, dentries[i].secon);
		if (ret)
			error("failed to set SELinux context on %s\n", dentries[i].path);
		ret = inode_set_capabilities(entry_inode, dentries[i].capabilities);
		if (ret)
			error("failed to set capability on %s\n", dentries[i].path);

		free(dentries[i].path);
		free(dentries[i].full_path);
		free(dentries[i].link);
		free((void *)dentries[i].filename);
		free(dentries[i].secon);
	}

	free(dentries);
	return inode;
}
Beispiel #23
0
rpmFileAction rpmfiDecideFateIndex(rpmfi ofi, int oix, rpmfi nfi, int nix,
				   int skipMissing)
{
    char * fn = rpmfiFNIndex(nfi, nix);
    rpmfileAttrs newFlags = rpmfiFFlagsIndex(nfi, nix);
    char buffer[1024];
    rpmFileTypes dbWhat, newWhat, diskWhat;
    struct stat sb;
    int save = (newFlags & RPMFILE_NOREPLACE) ? FA_ALTNAME : FA_SAVE;
    int action = FA_CREATE; /* assume we can create */

    /* If the new file is a ghost, leave whatever might be on disk alone. */
    if (newFlags & RPMFILE_GHOST) {
	action = FA_SKIP;
	goto exit;
    }

    if (lstat(fn, &sb)) {
	/*
	 * The file doesn't exist on the disk. Create it unless the new
	 * package has marked it as missingok, or allfiles is requested.
	 */
	if (skipMissing && (newFlags & RPMFILE_MISSINGOK)) {
	    rpmlog(RPMLOG_DEBUG, "%s skipped due to missingok flag\n",
			fn);
	    action = FA_SKIP;
	    goto exit;
	} else {
	    goto exit;
	}
    }

    diskWhat = rpmfiWhatis((rpm_mode_t)sb.st_mode);
    dbWhat = rpmfiWhatis(rpmfiFModeIndex(ofi, oix));
    newWhat = rpmfiWhatis(rpmfiFModeIndex(nfi, nix));

    /*
     * This order matters - we'd prefer to CREATE the file if at all
     * possible in case something else (like the timestamp) has changed.
     * Only regular files and symlinks might need a backup, everything
     * else falls through here with FA_CREATE.
     */
    memset(buffer, 0, sizeof(buffer));
    if (dbWhat == REG) {
	int oalgo, nalgo;
	size_t odiglen, ndiglen;
	const unsigned char * odigest, * ndigest;

	/* See if the file on disk is identical to the one in old pkg */
	odigest = rpmfiFDigestIndex(ofi, oix, &oalgo, &odiglen);
	if (diskWhat == REG) {
	    if (rpmDoDigest(oalgo, fn, 0, (unsigned char *)buffer, NULL))
	        goto exit;	/* assume file has been removed */
	    if (odigest && memcmp(odigest, buffer, odiglen) == 0)
	        goto exit;	/* unmodified config file, replace. */
	}

	/* See if the file on disk is identical to the one in new pkg */
	ndigest = rpmfiFDigestIndex(nfi, nix, &nalgo, &ndiglen);
	if (diskWhat == REG && newWhat == REG) {
	    /* hash algo changed in new, recalculate digest */
	    if (oalgo != nalgo)
		if (rpmDoDigest(nalgo, fn, 0, (unsigned char *)buffer, NULL))
		    goto exit;		/* assume file has been removed */
	    if (ndigest && memcmp(ndigest, buffer, ndiglen) == 0)
	        goto exit;		/* file identical in new, replace. */
	}

	/* If file can be determined identical in old and new pkg, let it be */
	if (newWhat == REG && oalgo == nalgo && odiglen == ndiglen) {
	    if (odigest && ndigest && memcmp(odigest, ndigest, odiglen) == 0) {
		action = FA_SKIP; /* identical file, dont bother */
		goto exit;
	    }
	}
	
	/* ...but otherwise a backup will be needed */
	action = save;
    } else if (dbWhat == LINK) {
	const char * oFLink, * nFLink;

	/* See if the link on disk is identical to the one in old pkg */
	oFLink = rpmfiFLinkIndex(ofi, oix);
	if (diskWhat == LINK) {
	    ssize_t link_len = readlink(fn, buffer, sizeof(buffer) - 1);
	    if (link_len == -1)
		goto exit;		/* assume file has been removed */
	    buffer[link_len] = '\0';
	    if (oFLink && rstreq(oFLink, buffer))
		goto exit;		/* unmodified config file, replace. */
	}

	/* See if the link on disk is identical to the one in new pkg */
	nFLink = rpmfiFLinkIndex(nfi, nix);
	if (diskWhat == LINK && newWhat == LINK) {
	    if (nFLink && rstreq(nFLink, buffer))
		goto exit;		/* unmodified config file, replace. */
	}

	/* If link is identical in old and new pkg, let it be */
	if (newWhat == LINK && oFLink && nFLink && rstreq(oFLink, nFLink)) {
	    action = FA_SKIP;		/* identical file, don't bother. */
	    goto exit;
	}

	/* ...but otherwise a backup will be needed */
	action = save;
    }

exit:
    free(fn);
    return action;
}
Beispiel #24
0
/**
 * Get the location of the application directory.
 * On OSX this is the .app bundle resource directory.
 * On Windows this is the directory the executable was launched from.
 * On Linux/BSD it's the executable's directory
 * @return NULL if it could not be determined
 */
char *Bgetappdir(void)
{
    char *dir = NULL;
    
#ifdef _WIN32
	TCHAR appdir[MAX_PATH];
    
	if (GetModuleFileName(NULL, appdir, MAX_PATH) > 0) {
		// trim off the filename
		char *slash = strrchr(appdir, '\\');
		if (slash) slash[0] = 0;
		dir = strdup(appdir);
    }

#elif defined __APPLE__
    CFBundleRef mainBundle;
    CFURLRef resUrl, fullUrl;
	CFStringRef str;
    const char *s;
    
    mainBundle = CFBundleGetMainBundle();
    if (!mainBundle) {
        return NULL;
    }
    
    resUrl = CFBundleCopyResourcesDirectoryURL(mainBundle);
    if (!resUrl) {
        return NULL;
    }
    fullUrl = CFURLCopyAbsoluteURL(resUrl);
    if (fullUrl) {
        CFRelease(resUrl);
        resUrl = fullUrl;
    }

	str = CFURLCopyFileSystemPath(resUrl, kCFURLPOSIXPathStyle);
    CFRelease(resUrl);
    if (!str) {
        return NULL;
    }
    
    s = CFStringGetCStringPtr(str, CFStringGetSystemEncoding());
    if (s) {
        dir = strdup(s);
    }
    CFRelease(str);
    
#elif defined(__linux) || defined(__NetBSD__) || defined(__OpenBSD__)
    char buf[PATH_MAX] = {0};
    char buf2[PATH_MAX] = {0};
#  ifdef __linux
    snprintf(buf, sizeof(buf), "/proc/%d/exe", getpid());
#  else // the BSDs.. except for FreeBSD which has a sysctl
    snprintf(buf, sizeof(buf), "/proc/%d/file", getpid());
#  endif
    int len = readlink(buf, buf2, sizeof(buf2));
    if (len != -1) {
        // remove executable name with dirname(3)
        // on Linux, dirname() will modify buf2 (cutting off executable name) and return it
        // on FreeBSD it seems to use some internal buffer instead.. anyway, just strdup()
        dir = strdup(dirname(buf2));
    }
#elif defined(__FreeBSD__)
    // the sysctl should also work when /proc/ is not mounted (which seems to
    // be common on FreeBSD), so use it..
    char buf[PATH_MAX] = {0};
    int name[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
    size_t len = sizeof(buf)-1;
    int ret = sysctl(name, sizeof(name)/sizeof(name[0]), buf, &len, NULL, 0);
    if(ret == 0 && buf[0] != '\0') {
        // again, remove executable name with dirname()
        // on FreeBSD dirname() seems to use some internal buffer
        dir = strdup(dirname(buf));
    }
#endif
    
    return dir;
}
Beispiel #25
0
void dumpnode(struct filenode *node, FILE *f)
{
	struct romfh ri;
	struct filenode *p;

	ri.nextfh = 0;
	ri.spec = 0;
	ri.size = htonl(node->size);
	ri.checksum = htonl(0x55555555);
	if (node->pad)
		dumpzero(node->pad, f);
	if (node->next && node->next->next)
		ri.nextfh = htonl(node->next->offset);
	if ((node->modes & 0111) &&
	    (S_ISDIR(node->modes) || S_ISREG(node->modes)))
		ri.nextfh |= htonl(ROMFH_EXEC);

	if (node->orig_link) {
		ri.nextfh |= htonl(ROMFH_HRD);
		/* Don't allow hardlinks to convey attributes */
		ri.nextfh &= ~htonl(ROMFH_EXEC);
		ri.spec = htonl(node->orig_link->offset);
		dumpri(&ri, node, f);
	} else if (S_ISDIR(node->modes)) {
		ri.nextfh |= htonl(ROMFH_DIR);
		if (listisempty(&node->dirlist)) {
			ri.spec = htonl(node->offset);
		} else {
			ri.spec = htonl(node->dirlist.head->offset);
		}
		dumpri(&ri, node, f);
	} else if (S_ISLNK(node->modes)) {
		ri.nextfh |= htonl(ROMFH_LNK);
		dumpri(&ri, node, f);
		memset(bigbuf, 0, sizeof(bigbuf));
		readlink(node->realname, bigbuf, node->size);
		dumpdataa(bigbuf, node->size, f);
	} else if (S_ISREG(node->modes)) {
		int offset, len, fd, max, avail;
		ri.nextfh |= htonl(ROMFH_REG);
		dumpri(&ri, node, f);
		offset = 0;
		max = node->size;
		/* XXX warn about size mismatch */
		fd = open(node->realname, O_RDONLY
#ifdef O_BINARY
| O_BINARY
#endif
);
		if (fd) {
			while(offset < max) {
				avail = max-offset < sizeof(bigbuf) ? max-offset : sizeof(bigbuf);
				len = read(fd, bigbuf, avail);
				if (len <= 0)
					break;
				dumpdata(bigbuf, len, f);
				offset+=len;
			}
			close(fd);
		}
		max = (max+15)&~15;
		while (offset < max) {
			avail = max-offset < sizeof(bigbuf) ? max-offset : sizeof(bigbuf);
			memset(bigbuf, 0, avail);
			dumpdata(bigbuf, avail, f);
			offset+=avail;
		}
	} else if (S_ISCHR(node->modes)) {
		ri.nextfh |= htonl(ROMFH_CHR);
		ri.spec = htonl(major(node->devnode)<<16|minor(node->devnode));
		dumpri(&ri, node, f);
	} else if (S_ISBLK(node->modes)) {
		ri.nextfh |= htonl(ROMFH_BLK);
		ri.spec = htonl(major(node->devnode)<<16|minor(node->devnode));
		dumpri(&ri, node, f);
	} else if (S_ISFIFO(node->modes)) {
		ri.nextfh |= htonl(ROMFH_FIF);
		dumpri(&ri, node, f);
	} else if (S_ISSOCK(node->modes)) {
		ri.nextfh |= htonl(ROMFH_SCK);
		dumpri(&ri, node, f);
	}

	p = node->dirlist.head;
	while (p->next) {
		dumpnode(p, f);
		p = p->next;
	}
}
static void
symlink_SCCS (char* s_path, char* d_path)
{
  struct stat dst_stat_buf;
  char symlink_buf[MAXPATHLEN + 1];
  int count;

  if (access (d_path, F_OK))			/* Does d_path exit? */
    {
      if (errno != ENOENT)
	{
	  if (!quiet_flag)
	    {
	      fprintf (stderr, "%s: error: can't check accessability of %s: %s\n",
	        pname, d_path, sys_errlist[errno]);
	      fprintf (stderr, "%s: input %s will be ignored\n",
	        pname, s_path);
	    }
	  return;
	}
    }
  else						/* d_path exists.  What is it? */
    {
      if (lstat (d_path, &dst_stat_buf) == -1)
	{
	  if (!quiet_flag)
	    {
	      fprintf (stderr, "%s: error: unable to get status of %s: %s\n",
	        pname, d_path, sys_errlist[errno]);
              fprintf (stderr, "%s: input %s will be ignored\n",
	        pname, s_path);
	    }
	  return;
	}

      if (S_ISLNK(dst_stat_buf.st_mode))	/* d_path is a symbolic link */
	{
          if ((count = readlink (d_path, symlink_buf, MAXPATHLEN)) == -1)
            {
              fprintf (stderr, "%s: error: can't read symlink %s: %s\n",
                pname, d_path, sys_errlist[errno]);
              fprintf (stderr, "%s: input file %s will be ignored\n",
                pname, s_path);
              return;
            }
          symlink_buf[count] = '\0';

          if (!strcmp(s_path, symlink_buf))	/* symlink = s_path. Done */
            {
              return;
            }
          else					/* symlink != s_path */
            {
	      if (force_flag)
                {
                  if (remove_item (s_path, d_path) != 0)
	            return;
                }
              else
	        {
	          if (!quiet_flag)
		    {
	              fprintf (stderr, "%s: error: Symbolic link %s already exists \
			but does not point to %s\n",
	                pname, d_path, s_path);
	              fprintf (stderr, "%s: input s %s will be ignored\n",
	                pname, s_path);
		    }
                  return;
                }
	    }
        }
      else					/* d_path is NOT a symbolic link */
	{
          if (force_flag)
	    {
              if (remove_item (s_path, d_path))
	        return;
	    }
          else
	    {
	      if (!quiet_flag)
		{
	          fprintf (stderr, "%s: error: output already exists: %s\n",
	            pname, d_path);
	          fprintf (stderr, "%s: input %s will be ignored\n",
	            pname, s_path);
		}
              return;
	    }
	}
    }
   
  if (symlink (s_path, d_path))
    {
      if (!quiet_flag)
        fprintf (stderr, "%s: error: can't symlink %s to %s: %s\n",
          pname, s_path, d_path, sys_errlist[errno]);
    }
  else
    {
      if (verbose_flag)
        fprintf (stderr, "%s: created symlink %s -> %s\n",
        pname, d_path, s_path);
    }
}
Beispiel #27
0
int sl_trustfile(const char *fname, uid_t *okusers, uid_t *badusers)
{
  char * fexp = NULL;	        /* file name fully expanded        */
  register char *p;             /* used to hold name to be checked */
  struct stat stbuf;	        /* used to check file permissions  */
  char c;			/* used to hold temp char          */
  
  int errgrp = 0;

  SL_ENTER(_("sl_trustfile"));
  if (fname == NULL)
    SL_IRETURN(SL_EBADFILE, _("sl_trustfile"));

  fexp = calloc(1, MAXFILENAME );
  if (!fexp)
    SL_IRETURN(SL_EMEM, _("sl_trustfile"));

  p = fexp;

  /*
   * next expand to the full file name
   * getfname sets sl_errno as appropriate
   */
#ifdef TRUST_MAIN
  sl_errno = getfname(fname, fexp, MAXFILENAME);
  if (sl_errno != 0)
    {
      free(fexp);
      return sl_errno;
    }
#else
  if (SL_ISERROR(getfname(fname, fexp, MAXFILENAME)))
    {
      free(fexp);
      SL_IRETURN(sl_errno, _("sl_trustfile"));
    }
#endif

  if (okusers == NULL && badusers == NULL)
    {
      okusers = rootonly;
      rootonly[EUIDSLOT] = tf_euid;
    }

  /*
   * now loop through the path a component at a time
   * note we have to special-case root
   */
  while(*p)
    {
      /*
       * get next component
       */
      while(*p && *p != '/')
	p++;

      /* save where you are 
       */
      if (p == fexp)
	{
	  /* keep the / if it's the root dir 
	   */
	  c    = p[1];
	  p[1] = '\0';
	}
      else
	{
	  /* clobber the / if it isn't the root dir 
	   */
	  c  = *p;
	  *p = '\0';
	}

      /*
       * now get the information
       */
      if (retry_lstat(FIL__, __LINE__, fexp, &stbuf) < 0)
	{
	  (void) strncpy(tf_path, fexp, sizeof(tf_path));
	  tf_path[sizeof(tf_path)-1] = '\0';
#ifdef TRUST_MAIN
	  fprintf(stderr, "---------------------------------------------\n");
	  fprintf(stderr, "trustfile: ESTAT: stat(%s) failed,\n", fexp);
	  fprintf(stderr, "maybe the file does not exist\n");
	  fprintf(stderr, "---------------------------------------------\n");
#endif
	  free(fexp);
	  SL_IRETURN(SL_ESTAT, _("sl_trustfile"));
	}

#ifdef S_IFLNK
      /* 
       * if it's a symbolic link, recurse
       */
      if ((stbuf.st_mode & S_IFLNK) == S_IFLNK)
	{
	  /*
	   * this is tricky
	   * if the symlink is to an absolute path
	   * name, just call trustfile on it; but
	   * if it's a relative path name, it's 
	   * interpreted WRT the current working
	   * directory AND NOT THE FILE NAME!!!!!
	   * so, we simply put /../ at the end of
	   * the file name, then append the symlink
	   * contents; trustfile will canonicalize
	   * this, and the /../ we added "undoes"
	   * the name of the symlink to put us in
	   * the current working directory, at
	   * which point the symlink contents (appended
	   * to the CWD) are interpreted correctly.
	   * got it?
	   */
	  char * csym;	                /* contents of symlink file  */
	  char * full;	                /* "full" name of symlink    */
	  char *b;                      /* used to copy stuff around */
	  const char *t;	        /* used to copy stuff around */
	  int lsym;	                /* num chars in symlink ref  */
	  int i;		        /* trustworthy or not?       */
	  const char * t_const;
	  char *end;

	  /*
	   * get what the symbolic link points to
	   *
	   * The original code does not check the return code of readlink(),
	   * and has an off-by-one error 
	   * (MAXFILENAME instead of MAXFILENAME-1)
	   * R.W. Tue May 29 22:05:16 CEST 2001
	   */
	  csym = calloc(1, MAXFILENAME );
	  if (!csym)
	    {
	      free(fexp);
	      SL_IRETURN(SL_EMEM, _("sl_trustfile"));
	    }

	  lsym = readlink(fexp, csym, MAXFILENAME-1);
	  if (lsym >= 0) 
	    csym[lsym] = '\0';
	  else
	    {
#ifdef TRUST_MAIN
	      fprintf(stderr, "---------------------------------------------\n");
	      fprintf(stderr, "trustfile: EBADNAME: readlink(%s) failed\n",
		      fexp);
	      fprintf(stderr, "---------------------------------------------\n");
#endif
	      free(csym);
	      free(fexp);
	      SL_IRETURN(SL_EBADNAME, _("sl_trustfile"));
	    }

	  full = calloc(1, MAXFILENAME );
	  if (!full)
	    {
	      free(csym);
	      free(fexp);
	      SL_IRETURN(SL_EMEM, _("sl_trustfile"));
	    }

	  /*
	   * relative or absolute referent?
	   */
	  if (csym[0] != '/')
	    {
	      /* pointer to one above last element
	       */
	      end = &full[MAXFILENAME-1]; ++end;

	      /* initialize pointers 
	       */
	      b = full;

	      /* copy in base path 
	       */
	      t = fexp;
	      while(*t && b < end)
		*b++ = *t++;

	      /* smack on the /../ 
	       */
	      t_const = "/../"; t = (const char *)t_const;
	      while(*t && b < end)
		*b++ = *t++;

	      /* append the symlink referent 
	       */
	      t = csym;
	      while(*t && b < end)
		*b++ = *t++;

	      /* see if we're too big 
	       */
	      if (*t || b == end)
		{
		  /* yes -- error 
		   */
		  (void) strncpy(tf_path, fexp, sizeof(tf_path));
		  tf_path[sizeof(tf_path)-1] = '\0';
#ifdef TRUST_MAIN
		  fprintf(stderr, "---------------------------------------------\n");
		  fprintf(stderr, 
			  "trustfile: ETRUNC: normalized path too long (%s)\n",
			  fexp);
		  fprintf(stderr, "---------------------------------------------\n");
#endif
		  free(full);
		  free(csym);
		  free(fexp);
		  SL_IRETURN(SL_ETRUNC, _("sl_trustfile"));
		}
	      *b = '\0';
	    }
	  else
	    {
	      /* absolute -- just copy                */
	      /* overflow can't occur as the arrays   */
	      /* are the same size		      */
	      (void) strcpy(full, csym);                 /* known to fit  */
	    }
	  /*
	   * now check out this file and its ancestors
	   */
	  if ((i = sl_trustfile(full, okusers, badusers)) != SL_ENONE)
	    {
	      free(full);
	      free(csym);
	      free(fexp);
	      SL_IRETURN(i, _("sl_trustfile"));
	    }

	  /*
	   * okay, this part is valid ... let's check the rest
	   * put the / back
	   */
	  if (p == fexp)
	    {
	      /* special case for root */
	      p[1] = c;
	      p++;
	    }
	  else
	    {
	      /* ordinary case for everything else */
	      *p = c;
	      if (*p)
		p++;
	    }
	  free(full);
	  free(csym);
	  continue;
	}
#endif

			
#ifdef TRUST_DEBUG
      fprintf(stderr, "\ntrustfile: checking path=%s\n", fexp); 
#endif 
      /*
       * if the owner is not trusted then -- as the owner can
       * change protection modes -- he/she can write to the
       * file regardless of permissions, so bomb
       */
      if (((okusers != NULL && S_FALSE == isin((uid_t)stbuf.st_uid,okusers))||
	   (badusers != NULL && S_TRUE == isin((uid_t)stbuf.st_uid,badusers))))
	{
#ifdef TRUST_DEBUG
	  fprintf(stderr, "---------------------------------------------\n");
	  fprintf(stderr, "trustfile: EBADUID %s (owner not trusted)\n", 
		  fexp); 
	  fprintf(stderr, "The owner of this file/directory is not in samhains\n"); 
	  fprintf(stderr, "list of trusted users.\n");
	  fprintf(stderr, "Please run ./configure again with the option\n");
	  fprintf(stderr, " ./configure [more options] --with-trusted=0,...,UID\n"); 
	  fprintf(stderr, "where UID is the UID of the (yet) untrusted user.\n"); 
	  fprintf(stderr, "---------------------------------------------\n");
#endif 
	  (void) strncpy(tf_path, fexp, sizeof(tf_path));
	  tf_path[sizeof(tf_path)-1] = '\0';

	  tf_baduid = (uid_t) stbuf.st_uid;
	  free(fexp);
	  SL_IRETURN(SL_EBADUID, _("sl_trustfile"));
	}

      /*
       * if a group member can write but the
       * member is not trusted, bomb; but if
       * sticky bit semantics are honored, it's
       * okay
       */
      /* Thu Mar 29 21:10:28 CEST 2001 Rainer Wichmann
       * replace !isingrp() with onlytrustedingrp(), as isingrp()
       * will return at the first trusted user, even if there are additional
       * (untrusted) users in the group
       */
      if (((stbuf.st_mode & S_IWGRP) == S_IWGRP) &&
	  ((okusers != NULL && !onlytrustedingrp((gid_t)stbuf.st_gid,okusers,&errgrp))||
	   (badusers != NULL && isingrp((gid_t)stbuf.st_gid, badusers,&errgrp)))
#ifdef STICKY
	  && ((stbuf.st_mode&S_IFDIR) != S_IFDIR ||
	      (stbuf.st_mode&S_ISVTX) != S_ISVTX)
#endif
	  )
	{
#ifdef TRUST_DEBUG
	  fprintf(stderr, "---------------------------------------------\n");
	  fprintf(stderr, 
		  "trustfile: EBADGID %ld %s (group member not trusted)\n", 
		  (UID_CAST)stbuf.st_gid, fexp);
	  fprintf(stderr, "This file/directory is group writeable, and one of the group members\n");
	  fprintf(stderr, "is not in samhains list of trusted users.\n"); 
	  fprintf(stderr, "Please run ./configure again with the option\n");
	  fprintf(stderr, " ./configure [more options] --with-trusted=0,...,UID\n"); 
	  fprintf(stderr, "where UID is the UID of the (yet) untrusted user.\n"); 
	  fprintf(stderr, "---------------------------------------------\n");
#endif 
	  (void) strncpy(tf_path, fexp, sizeof(tf_path));
	  tf_path[sizeof(tf_path)-1] = '\0';

	  tf_badgid = (gid_t) stbuf.st_gid;
	  free(fexp);
	  SL_IRETURN((errgrp == ERANGE) ? SL_ERANGE : SL_EBADGID, _("sl_trustfile"));
	}
      /*
       * if other can write, bomb; but if the sticky
       * bit semantics are honored, it's okay
       */
      if (((stbuf.st_mode & S_IWOTH) == S_IWOTH)
#ifdef STICKY
	  && ((stbuf.st_mode&S_IFDIR) != S_IFDIR ||
	      (stbuf.st_mode&S_ISVTX) != S_ISVTX)
#endif
	  )
	{
#ifdef TRUST_DEBUG
	  fprintf(stderr, "---------------------------------------------\n");
	  fprintf(stderr, "trustfile: EBADOTH (world writeable): %s\n", 
		  fexp);
	  fprintf(stderr, "This file/directory is world writeable.\n");
	  fprintf(stderr, "---------------------------------------------\n");
#endif 
	  (void) strncpy(tf_path, fexp, sizeof(tf_path));
	  tf_path[sizeof(tf_path)-1] = '\0';

	  free(fexp);
	  SL_IRETURN(SL_EBADOTH, _("sl_trustfile"));
	}
      /*
       * put the / back
       */
      if (p == fexp)
	{
	  /* special case for root */
	  p[1] = c;
	  p++;
	}
      else
	{
	  /* ordinary case for everything else */
	  *p = c;
	  if (*p)
	    p++;
	}
    }
  /*
   * yes, it can be trusted
   */
  (void) strncpy(tf_path, fexp, sizeof(tf_path));
  tf_path[sizeof(tf_path)-1] = '\0';

  free(fexp);
  SL_IRETURN(SL_ENONE, _("sl_trustfile"));
}
Beispiel #28
0
/* NOTE: Caller must free the pointer, if not NULL */
char * hb_fsLinkRead( const char * pszFile )
{
   char * pszLink = NULL;

   if( pszFile )
   {
      hb_vmUnlock();

#if defined( HB_OS_WIN ) && ! defined( HB_OS_WIN_CE )
      {
         typedef DWORD ( WINAPI * _HB_GETFINALPATHNAMEBYHANDLE )( HANDLE, LPTSTR, DWORD, DWORD );

         static _HB_GETFINALPATHNAMEBYHANDLE s_pGetFinalPathNameByHandle = NULL;

         #ifndef VOLUME_NAME_DOS
         #define VOLUME_NAME_DOS       0x0
         #endif
         #ifndef VOLUME_NAME_GUID
         #define VOLUME_NAME_GUID      0x1
         #endif
         #ifndef VOLUME_NAME_NT
         #define VOLUME_NAME_NT        0x2
         #endif
         #ifndef VOLUME_NAME_NONE
         #define VOLUME_NAME_NONE      0x4
         #endif
         #ifndef FILE_NAME_NORMALIZED
         #define FILE_NAME_NORMALIZED  0x0
         #endif
         #ifndef FILE_NAME_OPENED
         #define FILE_NAME_OPENED      0x8
         #endif

         if( ! s_pGetFinalPathNameByHandle )
         {
            HMODULE hModule = GetModuleHandle( TEXT( "kernel32.dll" ) );
            if( hModule )
               s_pGetFinalPathNameByHandle = ( _HB_GETFINALPATHNAMEBYHANDLE )
                  HB_WINAPI_GETPROCADDRESST( hModule, "GetFinalPathNameByHandle" );
         }

         if( s_pGetFinalPathNameByHandle )
         {
            LPCTSTR lpFileName;
            LPTSTR lpFileNameFree;
            HANDLE hFile;
            DWORD dwAttr;
            HB_BOOL fDir;

            lpFileName = HB_FSNAMECONV( pszFile, &lpFileNameFree );

            dwAttr = GetFileAttributes( lpFileName );
            fDir = ( dwAttr != INVALID_FILE_ATTRIBUTES ) &&
                   ( dwAttr & FILE_ATTRIBUTE_DIRECTORY );

            hFile = CreateFile( lpFileName,
                                GENERIC_READ,
                                FILE_SHARE_READ,
                                NULL,
                                OPEN_EXISTING,
                                fDir ? ( FILE_ATTRIBUTE_DIRECTORY | FILE_FLAG_BACKUP_SEMANTICS ) : FILE_ATTRIBUTE_NORMAL,
                                NULL );

            if( hFile == INVALID_HANDLE_VALUE )
            {
               hb_fsSetIOError( HB_FALSE, 0 );
               hb_fsSetFError( hb_fsError() );
            }
            else
            {
               DWORD size;
               TCHAR lpLink[ HB_PATH_MAX ];
               size = s_pGetFinalPathNameByHandle( hFile, lpLink, HB_PATH_MAX, VOLUME_NAME_DOS );
               if( size < HB_PATH_MAX )
               {
                  if( size > 0 )
                  {
                     lpLink[ size ] = TEXT( '\0' );
                     pszLink = HB_OSSTRDUP( lpLink );
                  }

                  hb_fsSetIOError( HB_TRUE, 0 );
                  hb_fsSetFError( hb_fsError() );
               }
               else
                  hb_fsSetFError( 1 );
            }

            if( lpFileNameFree )
               hb_xfree( lpFileNameFree );
         }
         else
            hb_fsSetFError( 1 );
      }
#elif defined( HB_OS_UNIX )
      {
         char * pszFileFree;
         size_t size;

         pszFile = hb_fsNameConv( pszFile, &pszFileFree );

         pszLink = ( char * ) hb_xgrab( HB_PATH_MAX + 1 );
         size = readlink( pszFile, pszLink, HB_PATH_MAX );
         hb_fsSetIOError( size != ( size_t ) -1, 0 );
         hb_fsSetFError( hb_fsError() );
         if( size == ( size_t ) -1 )
         {
            hb_xfree( pszLink );
            pszLink = NULL;
         }
         else
         {
            pszLink[ size ] = '\0';
            /* Convert from OS codepage */
            pszLink = ( char * ) hb_osDecodeCP( pszLink, NULL, NULL );
         }

         if( pszFileFree )
            hb_xfree( pszFileFree );
      }
#else
      {
         hb_fsSetFError( 1 );
      }
#endif

      hb_vmLock();
   }
   else
      hb_fsSetFError( 2 );

   return pszLink;
}
Beispiel #29
0
/**
 * Locate the Premake executable, and push its full path to the Lua stack.
 * Based on:
 * http://sourceforge.net/tracker/index.php?func=detail&aid=3351583&group_id=71616&atid=531880
 * http://stackoverflow.com/questions/933850/how-to-find-the-location-of-the-executable-in-c
 * http://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe
 */
int premake_locate_executable(lua_State* L, const char* argv0)
{
	char buffer[PATH_MAX];
	const char* path = NULL;

#if PLATFORM_WINDOWS
	DWORD len = GetModuleFileName(NULL, buffer, PATH_MAX);
	if (len > 0)
		path = buffer;
#endif

#if PLATFORM_MACOSX
	CFURLRef bundleURL = CFBundleCopyExecutableURL(CFBundleGetMainBundle());
	CFStringRef pathRef = CFURLCopyFileSystemPath(bundleURL, kCFURLPOSIXPathStyle);
	if (CFStringGetCString(pathRef, buffer, PATH_MAX - 1, kCFStringEncodingUTF8))
		path = buffer;
#endif

#if PLATFORM_LINUX
	int len = readlink("/proc/self/exe", buffer, PATH_MAX);
	if (len > 0)
		path = buffer;
#endif

#if PLATFORM_BSD
	int len = readlink("/proc/curproc/file", buffer, PATH_MAX);
	if (len < 0)
		len = readlink("/proc/curproc/exe", buffer, PATH_MAX);
	if (len > 0)
		path = buffer;
#endif

#if PLATFORM_SOLARIS
	int len = readlink("/proc/self/path/a.out", buffer, PATH_MAX);
	if (len > 0)
		path = buffer;
#endif

	/* As a fallback, search the PATH with argv[0] */
	if (!path)
	{
		lua_pushcfunction(L, os_pathsearch);
		lua_pushstring(L, argv0);
		lua_pushstring(L, getenv("PATH"));
		if (lua_pcall(L, 2, 1, 0) == OKAY && !lua_isnil(L, -1))
		{
			lua_pushstring(L, "/");
			lua_pushstring(L, argv0);
			lua_concat(L, 3);
			path = lua_tostring(L, -1);
		}
	}

	/* If all else fails, use argv[0] as-is and hope for the best */
	if (!path)
	{
		/* make it absolute, if needed */
		os_getcwd(L);
		lua_pushstring(L, "/");
		lua_pushstring(L, argv0);

		if (!path_isabsolute(L)) {
			lua_concat(L, 3);
		}
		else {
			lua_pop(L, 1);
		}

		path = lua_tostring(L, -1);
	}

	lua_pushstring(L, path);
	return 1;
}
Beispiel #30
0
int getService()
{
    struct dirent **proclist;
    char procname[80];
    char input[80];
    char procEntry[1024];
    int procFd;
    int proccount;
    int i, j, length;
    int pid = 0, ppid = 0, tgid = 0;

    int svccount = 0;
    int execount;

    /* Let's get our blob */
    proccount = scandir("/proc/", &proclist, proc_select, alphasort);
    /* get all proc dirs */
    if ((services = (svc_entry**)malloc(proccount * sizeof(svc_entry *))) 
                    == NULL) {
        return 0;
    }
    for (i = 0; i <proccount; i++ ) {
        snprintf(procname, 80, "/proc/%s/fd/0",  proclist[i]->d_name);
        if (readlink(procname, input, 80) <= 0) {
            free(proclist[i]);
            continue;
        }
        if ((strncmp(input, "/dev/null", 9) != 0)  &&
            (strncmp(input, "/dev/console", 12) != 0)) {
            free(proclist[i]);
            continue;
        }

        /*This is a service */
        snprintf(procname, 80, "/proc/%s/status",  proclist[i]->d_name);
        DEBUGMSGTL(("rec:log","service proc  status %s\n",procname));
        if ((procFd = open(procname, O_RDONLY)) == -1) {
            free(proclist[i]);
            continue;
        }
        if (read(procFd, procEntry, 1024) == -1) {
            free(proclist[i]);
            close(procFd);
            continue;
        }
        for (j = 0; j < MAX_PROC_ITEMS; j++) {
            values[j] = strstr(procEntry, proc_items[j]);
            if (values[j] != NULL ) {
                values[j] += (strlen(proc_items[j]) + 1);
            }
        }
        if (values[PROC_PPID] != NULL) {
            if ((ppid = atoi(values[PROC_PPID])) != 1) {
                free(proclist[i]);
                close(procFd);
                continue;
            }
        }
        /* Not daemonized so continue */
        if (values[PROC_PID] != NULL)
            pid = atoi(values[PROC_PID]);
        DEBUGMSGTL(("rec:log","service proc pid = %d \n", pid));
        if (values[PROC_TGID] != NULL)
            tgid = atoi(values[PROC_TGID]);
        DEBUGMSGTL(("rec:log","service proc tgid = %d \n", tgid));
        if (tgid != pid) {
            close(procFd);
            free(proclist[i]);
            continue;
        }

        length = index(values[PROC_NAME], 0x0a) - values[PROC_NAME];
        if ((services[svccount] = (svc_entry*)malloc(sizeof(svc_entry))) 
                                        == NULL) {
            close(procFd);
            free(proclist[i]);
            continue;
        }
        memset(services[svccount], 0, sizeof(svc_entry));
        services[svccount]-> pid = pid;
        services[svccount]-> ppid = ppid;
        services[svccount]-> tgid = tgid;
        services[svccount]->name = malloc(length + 1);
        memset(services[svccount]->name, 0, length + 1);
        strncpy(services[svccount]->name, values[PROC_NAME], length);
        DEBUGMSGTL(("rec:log","service proc name %s\n",  services[svccount]->name));
        /* not a thread */
        services[svccount]->filename = malloc(256);
        memset(services[svccount]->filename, 0, 256);
        snprintf(procname, 80, "/proc/%s/exe",  proclist[i]->d_name);
        if ((execount = readlink(procname, services[svccount]->filename, 256)) 
                        == -1) {
            free(proclist[i]);
            close(procFd);
            if (services[svccount]->filename != NULL )
                free(services[svccount]->filename);
            if (services[svccount]->name != NULL )
                free(services[svccount]->name);
            free(services[svccount]);
            continue;
        }
        DEBUGMSGTL(("rec:log","service file name %s\n", 
                                services[svccount]->filename));
        svccount++;
        free(proclist[i]);
        close(procFd);
    }
    free(proclist);
    return svccount;
}