Skip to content

Commit

Permalink
support colon in filenames
Browse files Browse the repository at this point in the history
Problem: It is impossible to feed filenames with the character colon because
qemu interprets such names as a protocol. For example filename scsi:0, is
interpreted as a protocol by name "scsi".

This patch allows user to espace colon characters. For example the above
filename can now be expressed either as 'scsi\:0' or as file:scsi:0

anything following the "file:" tag is interpreted verbatin. However if "file:"
tag is omitted then any colon characters in the string must be escaped using
backslash.

Here are couple of examples:

scsi\:0\:abc is a local file scsi:0:abc
http\://myweb is a local file by name http://myweb
file:scsi:0:abc is a local file scsi:0:abc
file:http://myweb is a local file by name http://myweb

Signed-off-by: Ram Pai <[email protected]>
Signed-off-by: Anthony Liguori <[email protected]>
  • Loading branch information
Ram Pai authored and Anthony Liguori committed Jun 29, 2009
1 parent ab4e560 commit 707c0db
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 11 deletions.
27 changes: 17 additions & 10 deletions block.c
Original file line number Diff line number Diff line change
Expand Up @@ -225,22 +225,17 @@ static BlockDriver *find_protocol(const char *filename)
{
BlockDriver *drv1;
char protocol[128];
int len;
int len = strnlen(filename, 127)+1;
const char *p;

#ifdef _WIN32
if (is_windows_drive(filename) ||
is_windows_drive_prefix(filename))
return bdrv_find_format("raw");
#endif
p = strchr(filename, ':');
if (!p)
p = fill_token(protocol, len, filename, ':');
if (*p != ':')
return bdrv_find_format("raw");
len = p - filename;
if (len > sizeof(protocol) - 1)
len = sizeof(protocol) - 1;
memcpy(protocol, filename, len);
protocol[len] = '\0';
for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
if (drv1->protocol_name &&
!strcmp(drv1->protocol_name, protocol))
Expand Down Expand Up @@ -414,9 +409,9 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
open_flags = BDRV_O_RDWR | (flags & BDRV_O_CACHE_MASK);
else
open_flags = flags & ~(BDRV_O_FILE | BDRV_O_SNAPSHOT);
ret = drv->bdrv_open(bs, filename, open_flags);
ret = bdrv_open3(bs, filename, open_flags, drv);
if ((ret == -EACCES || ret == -EPERM) && !(flags & BDRV_O_FILE)) {
ret = drv->bdrv_open(bs, filename, open_flags & ~BDRV_O_RDWR);
ret = bdrv_open3(bs, filename, open_flags & ~BDRV_O_RDWR, drv);
bs->read_only = 1;
}
if (ret < 0) {
Expand Down Expand Up @@ -461,6 +456,18 @@ int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
return 0;
}

int bdrv_open3(BlockDriverState *bs, const char *filename, int flags, BlockDriver *drv)
{
char myfile[PATH_MAX];
const char *f;

if (!strstart(filename, "file:", &f)) {
fill_token(myfile, PATH_MAX, filename, '\0');
return drv->bdrv_open(bs,myfile,flags);
}
return drv->bdrv_open(bs,f,flags);
}

void bdrv_close(BlockDriverState *bs)
{
if (bs->drv) {
Expand Down
2 changes: 2 additions & 0 deletions block.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags);
int bdrv_open(BlockDriverState *bs, const char *filename, int flags);
int bdrv_open2(BlockDriverState *bs, const char *filename, int flags,
BlockDriver *drv);
int bdrv_open3(BlockDriverState *bs, const char *filename, int flags,
BlockDriver *drv);
void bdrv_close(BlockDriverState *bs);
int bdrv_check(BlockDriverState *bs);
int bdrv_read(BlockDriverState *bs, int64_t sector_num,
Expand Down
2 changes: 1 addition & 1 deletion block/dmg.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ static int dmg_open(BlockDriverState *bs, const char *filename, int flags)
close(s->fd);
/* open raw instead */
bs->drv=bdrv_find_format("raw");
return bs->drv->bdrv_open(bs, filename, flags);
return bdrv_open3(bs, filename, flags, bs->drv);
}
info_begin=read_off(s->fd);
if(info_begin==0)
Expand Down
1 change: 1 addition & 0 deletions block/raw-posix.c
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,7 @@ static BlockDriver bdrv_raw = {
.bdrv_getlength = raw_getlength,

.create_options = raw_create_options,
.protocol_name = "file",
};

/***********************************************/
Expand Down
26 changes: 26 additions & 0 deletions cutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,32 @@
#include "qemu-common.h"
#include "host-utils.h"

/*
* fill first 'len' characters of 'buff' with pruned
* contents of 'str' delimited by the character 'c'.
* Escape character '\' is pruned off.
* Return pointer to the delimiting character.
*/
const char *fill_token(char *buf, const int len, const char *str, const char c)
{
const char *p=str;
char *q=buf;

while (p < str+len-1) {
if (*p == c)
break;
if (*p == '\\') {
p++;
if (*p == '\0')
break;
}
*q++ = *p++;
}
*q='\0';
return p;
}


void pstrcpy(char *buf, int buf_size, const char *str)
{
int c;
Expand Down
1 change: 1 addition & 0 deletions qemu-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ void qemu_get_timedate(struct tm *tm, int offset);
int qemu_timedate_diff(struct tm *tm);

/* cutils.c */
const char *fill_token(char *buf, int buf_size, const char *str, char);
void pstrcpy(char *buf, int buf_size, const char *str);
char *pstrcat(char *buf, int buf_size, const char *s);
int strstart(const char *str, const char *val, const char **ptr);
Expand Down

0 comments on commit 707c0db

Please sign in to comment.