Skip to content
Snippets Groups Projects
utils.c 27.3 KiB
Newer Older
  • Learn to ignore specific revisions
  • /*!
     * core handler for dynamic strings.
     * This is not meant to be called directly, but rather through the
     * various wrapper macros
    
     *	ast_str_set(...)
     *	ast_str_append(...)
     *	ast_str_set_va(...)
     *	ast_str_append_va(...)
    
    int __ast_str_helper(struct ast_str **buf, size_t max_len,
    	int append, const char *fmt, va_list ap)
    
    Luigi Rizzo's avatar
    Luigi Rizzo committed
    	int res, need;
    
    	int offset = (append && (*buf)->len) ? (*buf)->used : 0;
    
    	if (max_len < 0)
    		max_len = (*buf)->len;	/* don't exceed the allocated space */
    	/*
    	 * Ask vsnprintf how much space we need. Remember that vsnprintf
    	 * does not count the final '\0' so we must add 1.
    	 */
    
    	res = vsnprintf((*buf)->str + offset, (*buf)->len - offset, fmt, ap);
    
    
    Luigi Rizzo's avatar
    Luigi Rizzo committed
    	need = res + offset + 1;
    
    	/*
    	 * If there is not enough space and we are below the max length,
    	 * reallocate the buffer and return a message telling to retry.
    	 */
    
    Luigi Rizzo's avatar
    Luigi Rizzo committed
    	if (need > (*buf)->len && (max_len == 0 || (*buf)->len < max_len) ) {
    
    		if (max_len && max_len < need)	/* truncate as needed */
    
    Luigi Rizzo's avatar
    Luigi Rizzo committed
    			need = max_len;
    
    Luigi Rizzo's avatar
    Luigi Rizzo committed
    		else if (max_len == 0)	/* if unbounded, give more room for next time */
    			need += 16 + need/4;
    		if (0)	/* debugging */
    			ast_verbose("extend from %d to %d\n", (int)(*buf)->len, need);
    		if (ast_str_make_space(buf, need)) {
    			ast_verbose("failed to extend from %d to %d\n", (int)(*buf)->len, need);
    
    			return AST_DYNSTR_BUILD_FAILED;
    
    Luigi Rizzo's avatar
    Luigi Rizzo committed
    		}
    
    		(*buf)->str[offset] = '\0';	/* Truncate the partial write. */
    
    		/* va_end() and va_start() must be done before calling
    		 * vsnprintf() again. */
    		return AST_DYNSTR_BUILD_RETRY;
    	}
    
    	/* update space used, keep in mind the truncation */
    	(*buf)->used = (res + offset > (*buf)->len) ? (*buf)->len : res + offset;
    
    
    void ast_enable_packet_fragmentation(int sock)
    {
    
    #if defined(HAVE_IP_MTU_DISCOVER)
    
    	int val = IP_PMTUDISC_DONT;
    	
    	if (setsockopt(sock, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val)))
    		ast_log(LOG_WARNING, "Unable to disable PMTU discovery. Large UDP packets may fail to be delivered when sent from this socket.\n");
    
    #endif /* HAVE_IP_MTU_DISCOVER */
    
    
    int ast_mkdir(const char *path, int mode)
    {
    	char *ptr;
    	int len = strlen(path), count = 0, x, piececount = 0;
    	char *tmp = ast_strdupa(path);
    	char **pieces;
    	char *fullpath = alloca(len + 1);
    	int res = 0;
    
    	for (ptr = tmp; *ptr; ptr++) {
    		if (*ptr == '/')
    			count++;
    	}
    
    	/* Count the components to the directory path */
    	pieces = alloca(count * sizeof(*pieces));
    	for (ptr = tmp; *ptr; ptr++) {
    		if (*ptr == '/') {
    			*ptr = '\0';
    			pieces[piececount++] = ptr + 1;
    		}
    	}
    
    	*fullpath = '\0';
    	for (x = 0; x < piececount; x++) {
    		/* This looks funky, but the buffer is always ideally-sized, so it's fine. */
    		strcat(fullpath, "/");
    		strcat(fullpath, pieces[x]);
    		res = mkdir(fullpath, mode);
    		if (res && errno != EEXIST)
    			return errno;
    	}
    	return 0;
    }